@theia/dev-container 1.67.0-next.13 → 1.67.0-next.56

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 +10 -1
  2. package/package.json +6 -6
  3. package/src/electron-browser/container-info-contribution.ts +2 -2
  4. package/src/electron-node/dev-container-backend-module.ts +3 -0
  5. package/src/electron-node/devcontainer-file.ts +4 -0
  6. package/src/electron-node/docker-compose/compose-service.ts +79 -0
  7. package/src/electron-node/docker-container-service.ts +18 -3
  8. package/src/electron-node/remote-container-connection-provider.ts +41 -7
  9. package/lib/dev-container-server/dev-container-server.d.ts +0 -2
  10. package/lib/dev-container-server/dev-container-server.d.ts.map +0 -1
  11. package/lib/dev-container-server/dev-container-server.js +0 -48
  12. package/lib/dev-container-server/dev-container-server.js.map +0 -1
  13. package/lib/electron-browser/container-connection-contribution.d.ts +0 -29
  14. package/lib/electron-browser/container-connection-contribution.d.ts.map +0 -1
  15. package/lib/electron-browser/container-connection-contribution.js +0 -156
  16. package/lib/electron-browser/container-connection-contribution.js.map +0 -1
  17. package/lib/electron-browser/container-info-contribution.d.ts +0 -20
  18. package/lib/electron-browser/container-info-contribution.d.ts.map +0 -1
  19. package/lib/electron-browser/container-info-contribution.js +0 -85
  20. package/lib/electron-browser/container-info-contribution.js.map +0 -1
  21. package/lib/electron-browser/container-output-provider.d.ts +0 -8
  22. package/lib/electron-browser/container-output-provider.d.ts.map +0 -1
  23. package/lib/electron-browser/container-output-provider.js +0 -41
  24. package/lib/electron-browser/container-output-provider.js.map +0 -1
  25. package/lib/electron-browser/dev-container-frontend-module.d.ts +0 -4
  26. package/lib/electron-browser/dev-container-frontend-module.d.ts.map +0 -1
  27. package/lib/electron-browser/dev-container-frontend-module.js +0 -42
  28. package/lib/electron-browser/dev-container-frontend-module.js.map +0 -1
  29. package/lib/electron-common/container-output-provider.d.ts +0 -4
  30. package/lib/electron-common/container-output-provider.d.ts.map +0 -1
  31. package/lib/electron-common/container-output-provider.js +0 -18
  32. package/lib/electron-common/container-output-provider.js.map +0 -1
  33. package/lib/electron-common/dev-container-workspaces.d.ts +0 -3
  34. package/lib/electron-common/dev-container-workspaces.d.ts.map +0 -1
  35. package/lib/electron-common/dev-container-workspaces.js +0 -21
  36. package/lib/electron-common/dev-container-workspaces.js.map +0 -1
  37. package/lib/electron-common/remote-container-connection-provider.d.ts +0 -30
  38. package/lib/electron-common/remote-container-connection-provider.d.ts.map +0 -1
  39. package/lib/electron-common/remote-container-connection-provider.js +0 -21
  40. package/lib/electron-common/remote-container-connection-provider.js.map +0 -1
  41. package/lib/electron-node/dev-container-backend-module.d.ts +0 -5
  42. package/lib/electron-node/dev-container-backend-module.d.ts.map +0 -1
  43. package/lib/electron-node/dev-container-backend-module.js +0 -61
  44. package/lib/electron-node/dev-container-backend-module.js.map +0 -1
  45. package/lib/electron-node/dev-container-file-service.d.ts +0 -15
  46. package/lib/electron-node/dev-container-file-service.d.ts.map +0 -1
  47. package/lib/electron-node/dev-container-file-service.js +0 -105
  48. package/lib/electron-node/dev-container-file-service.js.map +0 -1
  49. package/lib/electron-node/dev-container-workspace-handler.d.ts +0 -7
  50. package/lib/electron-node/dev-container-workspace-handler.d.ts.map +0 -1
  51. package/lib/electron-node/dev-container-workspace-handler.js +0 -21
  52. package/lib/electron-node/dev-container-workspace-handler.js.map +0 -1
  53. package/lib/electron-node/devcontainer-contributions/cli-enhancing-creation-contributions.d.ts +0 -17
  54. package/lib/electron-node/devcontainer-contributions/cli-enhancing-creation-contributions.d.ts.map +0 -1
  55. package/lib/electron-node/devcontainer-contributions/cli-enhancing-creation-contributions.js +0 -69
  56. package/lib/electron-node/devcontainer-contributions/cli-enhancing-creation-contributions.js.map +0 -1
  57. package/lib/electron-node/devcontainer-contributions/main-container-creation-contributions.d.ts +0 -41
  58. package/lib/electron-node/devcontainer-contributions/main-container-creation-contributions.d.ts.map +0 -1
  59. package/lib/electron-node/devcontainer-contributions/main-container-creation-contributions.js +0 -209
  60. package/lib/electron-node/devcontainer-contributions/main-container-creation-contributions.js.map +0 -1
  61. package/lib/electron-node/devcontainer-contributions/profile-file-modification-contribution.d.ts +0 -11
  62. package/lib/electron-node/devcontainer-contributions/profile-file-modification-contribution.d.ts.map +0 -1
  63. package/lib/electron-node/devcontainer-contributions/profile-file-modification-contribution.js +0 -37
  64. package/lib/electron-node/devcontainer-contributions/profile-file-modification-contribution.js.map +0 -1
  65. package/lib/electron-node/devcontainer-contributions/variable-resolver-contribution.d.ts +0 -18
  66. package/lib/electron-node/devcontainer-contributions/variable-resolver-contribution.d.ts.map +0 -1
  67. package/lib/electron-node/devcontainer-contributions/variable-resolver-contribution.js +0 -58
  68. package/lib/electron-node/devcontainer-contributions/variable-resolver-contribution.js.map +0 -1
  69. package/lib/electron-node/devcontainer-file.d.ts +0 -350
  70. package/lib/electron-node/devcontainer-file.d.ts.map +0 -1
  71. package/lib/electron-node/devcontainer-file.js +0 -18
  72. package/lib/electron-node/devcontainer-file.js.map +0 -1
  73. package/lib/electron-node/docker-container-service.d.ts +0 -30
  74. package/lib/electron-node/docker-container-service.d.ts.map +0 -1
  75. package/lib/electron-node/docker-container-service.js +0 -107
  76. package/lib/electron-node/docker-container-service.js.map +0 -1
  77. package/lib/electron-node/remote-container-connection-provider.d.ts +0 -82
  78. package/lib/electron-node/remote-container-connection-provider.d.ts.map +0 -1
  79. package/lib/electron-node/remote-container-connection-provider.js +0 -317
  80. package/lib/electron-node/remote-container-connection-provider.js.map +0 -1
  81. package/lib/package.spec.d.ts +0 -1
  82. package/lib/package.spec.d.ts.map +0 -1
  83. package/lib/package.spec.js +0 -26
  84. package/lib/package.spec.js.map +0 -1
package/README.md CHANGED
@@ -16,7 +16,7 @@ The `@theia/dev-container` extension provides functionality to create, start and
16
16
  [vscode Dev Containers extension](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers).
17
17
 
18
18
  The full devcontainer.json Schema can be found [here](https://containers.dev/implementors/json_reference/).
19
- Currently only a small number of configuration file properties are implemented. Those include the following:
19
+ Currently not all of the configuration file properties are implemented. The following are implemented:
20
20
 
21
21
  - name
22
22
  - Image
@@ -25,11 +25,20 @@ Currently only a small number of configuration file properties are implemented.
25
25
  - location
26
26
  - forwardPorts
27
27
  - mounts
28
+ - containerEnv
29
+ - remoteUser
30
+ - shutdownAction
31
+ - postCreateCommand
32
+ - postStartCommand
28
33
 
29
34
  see `main-container-creation-contributions.ts` for how to implementations or how to implement additional ones.
30
35
 
36
+ Additionally adds support for `composeUpArgs` devcontainer.json property to apply additional arguments for the `docker compose up` call.
37
+ Usage: `"composeUpArgs": ["--force-recreate"]`
38
+
31
39
  ## Additional Information
32
40
 
41
+ - [API documentation for `@theia/dev-container`](https://eclipse-theia.github.io/theia/docs/next/modules/_theia_dev-container.html)
33
42
  - [Theia - GitHub](https://github.com/eclipse-theia/theia)
34
43
  - [Theia - Website](https://theia-ide.org/)
35
44
 
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@theia/dev-container",
3
- "version": "1.67.0-next.13+c409d5d18",
3
+ "version": "1.67.0-next.56+d8f18cc386c",
4
4
  "description": "Theia - Editor Preview Extension",
5
5
  "dependencies": {
6
- "@theia/core": "1.67.0-next.13+c409d5d18",
7
- "@theia/output": "1.67.0-next.13+c409d5d18",
8
- "@theia/remote": "1.67.0-next.13+c409d5d18",
9
- "@theia/workspace": "1.67.0-next.13+c409d5d18",
6
+ "@theia/core": "1.67.0-next.56+d8f18cc386c",
7
+ "@theia/output": "1.67.0-next.56+d8f18cc386c",
8
+ "@theia/remote": "1.67.0-next.56+d8f18cc386c",
9
+ "@theia/workspace": "1.67.0-next.56+d8f18cc386c",
10
10
  "dockerode": "^4.0.2",
11
11
  "jsonc-parser": "^2.2.0",
12
12
  "uuid": "^8.0.0"
@@ -51,5 +51,5 @@
51
51
  "nyc": {
52
52
  "extends": "../../configs/nyc.json"
53
53
  },
54
- "gitHead": "c409d5d18d8c4f5a722f87b37ea9d6fd5af47ea8"
54
+ "gitHead": "d8f18cc386c45a736cd193d42eab02c8f64c6b10"
55
55
  }
@@ -44,13 +44,13 @@ export class ContainerInfoContribution implements FrontendApplicationContributio
44
44
  const containerInfo = await this.connectionProvider.getCurrentContainerInfo(containerPort);
45
45
  this.status = await this.remoteStatusService.getStatus(containerPort);
46
46
 
47
- this.portForwardingService.forwardedPorts = Object.entries(containerInfo?.NetworkSettings.Ports ?? {}).flatMap(([_, ports]) => (
47
+ this.portForwardingService.forwardedPorts.push(...Object.entries(containerInfo?.NetworkSettings.Ports ?? {}).flatMap(([_, ports]) => (
48
48
  ports.map(port => ({
49
49
  editing: false,
50
50
  address: port.HostIp ?? '',
51
51
  localPort: parseInt(port.HostPort ?? '0'),
52
52
  origin: 'container'
53
- }))));
53
+ })))));
54
54
  }
55
55
 
56
56
  enhanceTitle(title: string, parts: Map<string, string | undefined>): string {
@@ -29,6 +29,7 @@ import { ProfileFileModificationContribution } from './devcontainer-contribution
29
29
  import { DevContainerWorkspaceHandler } from './dev-container-workspace-handler';
30
30
  import { WorkspaceHandlerContribution } from '@theia/workspace/lib/node/default-workspace-server';
31
31
  import { registerVariableResolverContributions, VariableResolverContribution } from './devcontainer-contributions/variable-resolver-contribution';
32
+ import { DockerComposeService } from './docker-compose/compose-service';
32
33
 
33
34
  export const remoteConnectionModule = ConnectionContainerModule.create(({ bind, bindBackendService }) => {
34
35
  bindContributionProvider(bind, ContainerCreationContribution);
@@ -54,6 +55,8 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
54
55
  bind(DockerContainerService).toSelf().inSingletonScope();
55
56
  bind(ConnectionContainerModule).toConstantValue(remoteConnectionModule);
56
57
 
58
+ bind(DockerComposeService).toSelf().inSingletonScope();
59
+
57
60
  bind(DevContainerFileService).toSelf().inSingletonScope();
58
61
 
59
62
  bind(ExtensionsContribution).toSelf().inSingletonScope();
@@ -161,6 +161,10 @@ export interface ComposeContainer {
161
161
  * Whether to overwrite the command specified in the image. The default is false.
162
162
  */
163
163
  overrideCommand?: boolean
164
+ /**
165
+ * Allows passing additional arguments to the 'docker compose up' command.
166
+ */
167
+ composeUpArgs?: string[]
164
168
  [k: string]: unknown
165
169
  }
166
170
 
@@ -0,0 +1,79 @@
1
+ // *****************************************************************************
2
+ // Copyright (C) 2025 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 } from '@theia/core/shared/inversify';
18
+ import * as Docker from 'dockerode';
19
+ import { ComposeContainer, DevContainerConfiguration } from '../devcontainer-file';
20
+ import { ContainerOutputProvider } from '../../electron-common/container-output-provider';
21
+ import { spawn } from 'child_process';
22
+ import path = require('path');
23
+
24
+ @injectable()
25
+ export class DockerComposeService {
26
+
27
+ async createContainers(
28
+ devcontainerConfig: DevContainerConfiguration,
29
+ containerCreateOptions: Docker.ContainerCreateOptions,
30
+ outputProvider?: ContainerOutputProvider): Promise<string> {
31
+
32
+ if (!devcontainerConfig.dockerComposeFile || typeof devcontainerConfig.dockerComposeFile !== 'string') {
33
+ throw new Error('dockerComposeFile is not defined in devcontainer configuration. Multiple files are not supported currently');
34
+ }
35
+
36
+ const dockerComposeFilePath = resolveComposeFilePath(devcontainerConfig);
37
+
38
+ const composeUpArgs = Array.isArray(devcontainerConfig.composeUpArgs) ? devcontainerConfig.composeUpArgs : [];
39
+ await this.executeComposeCommand(dockerComposeFilePath, 'up', ['--detach', ...composeUpArgs], outputProvider);
40
+
41
+ return (devcontainerConfig as ComposeContainer).service;
42
+ }
43
+
44
+ protected executeComposeCommand(composeFilePath: string, command: string, args: string[], outputProvider?: ContainerOutputProvider): Promise<string> {
45
+ return new Promise<string>((resolve, reject) => {
46
+ const process = spawn('docker', ['compose', '-f', composeFilePath, command, ...args]);
47
+ process.stdout.on('data', data => {
48
+ outputProvider?.onRemoteOutput(data.toString());
49
+ });
50
+ process.stderr.on('data', data => {
51
+ outputProvider?.onRemoteOutput(data.toString());
52
+ });
53
+ process.on('close', code => {
54
+ outputProvider?.onRemoteOutput(`docker compose process exited with code ${code}`);
55
+ if (code === 0) {
56
+ resolve(''); // TODO return real container ids
57
+ } else {
58
+ reject(new Error(`docker compose process exited with code ${code}`));
59
+ }
60
+ });
61
+ });
62
+ }
63
+ }
64
+
65
+ export function resolveComposeFilePath(devcontainerConfig: DevContainerConfiguration): string {
66
+ if (!devcontainerConfig.dockerComposeFile) {
67
+ throw new Error('dockerComposeFile is not defined in devcontainer configuration.');
68
+ }
69
+
70
+ if (typeof devcontainerConfig.dockerComposeFile !== 'string') {
71
+ throw new Error('Multiple docker compose files are not supported currently.');
72
+ }
73
+
74
+ if (path.isAbsolute(devcontainerConfig.dockerComposeFile)) {
75
+ return devcontainerConfig.dockerComposeFile;
76
+ } else {
77
+ return path.resolve(path.dirname(devcontainerConfig.location!), devcontainerConfig.dockerComposeFile);
78
+ }
79
+ }
@@ -24,6 +24,7 @@ import { DevContainerConfiguration } from './devcontainer-file';
24
24
  import { DevContainerFileService } from './dev-container-file-service';
25
25
  import { ContainerOutputProvider } from '../electron-common/container-output-provider';
26
26
  import { RemoteDockerContainerConnection } from './remote-container-connection-provider';
27
+ import { DockerComposeService } from './docker-compose/compose-service';
27
28
 
28
29
  export const ContainerCreationContribution = Symbol('ContainerCreationContributions');
29
30
 
@@ -60,6 +61,9 @@ export class DockerContainerService {
60
61
  @inject(DevContainerFileService)
61
62
  protected readonly devContainerFileService: DevContainerFileService;
62
63
 
64
+ @inject(DockerComposeService)
65
+ protected readonly dockerComposeService: DockerComposeService;
66
+
63
67
  container: Docker.Container | undefined;
64
68
 
65
69
  async getOrCreateContainer(docker: Docker, options: ContainerConnectionOptions, outputProvider?: ContainerOutputProvider): Promise<Docker.Container> {
@@ -121,9 +125,19 @@ export class DockerContainerService {
121
125
  await containerCreateContrib.handleContainerCreation?.(containerCreateOptions, devcontainerConfig, docker, outputProvider);
122
126
  }
123
127
 
124
- // TODO add more config
125
- const container = await docker.createContainer(containerCreateOptions);
126
- await container.start();
128
+ let container: Docker.Container;
129
+
130
+ if (devcontainerConfig.dockerComposeFile) {
131
+ const containerName = await this.dockerComposeService.createContainers(devcontainerConfig, containerCreateOptions, outputProvider);
132
+ const services = await docker.listContainers({ filters: { label: [`com.docker.compose.service=${containerName}`] } });
133
+ if (services.length === 0) {
134
+ throw new Error(`No running container found for docker compose service ${containerName}`);
135
+ }
136
+ container = docker.getContainer(services[0].Id);
137
+ } else {
138
+ container = await docker.createContainer(containerCreateOptions);
139
+ await container.start();
140
+ }
127
141
 
128
142
  for (const containerCreateContrib of this.containerCreationContributions.getContributions()) {
129
143
  await containerCreateContrib.handlePostCreate?.(devcontainerConfig, container, docker, outputProvider);
@@ -131,4 +145,5 @@ export class DockerContainerService {
131
145
 
132
146
  return container;
133
147
  }
148
+
134
149
  }
@@ -25,7 +25,7 @@ import { RemoteConnectionService } from '@theia/remote/lib/electron-node/remote-
25
25
  import { RemoteProxyServerProvider } from '@theia/remote/lib/electron-node/remote-proxy-server-provider';
26
26
  import { Emitter, Event, generateUuid, MessageService, RpcServer, ILogger } from '@theia/core';
27
27
  import { Socket } from 'net';
28
- import { inject, injectable } from '@theia/core/shared/inversify';
28
+ import { inject, injectable, named } from '@theia/core/shared/inversify';
29
29
  import * as Docker from 'dockerode';
30
30
  import { DockerContainerService } from './docker-container-service';
31
31
  import { Deferred } from '@theia/core/lib/common/promise-util';
@@ -34,6 +34,8 @@ import { PassThrough } from 'stream';
34
34
  import { exec, execSync } from 'child_process';
35
35
  import { DevContainerFileService } from './dev-container-file-service';
36
36
  import { ContainerOutputProvider } from '../electron-common/container-output-provider';
37
+ import { DevContainerConfiguration } from './devcontainer-file';
38
+ import { resolveComposeFilePath } from './docker-compose/compose-service';
37
39
 
38
40
  @injectable()
39
41
  export class DevContainerConnectionProvider implements RemoteContainerConnectionProvider, RpcServer<ContainerOutputProvider> {
@@ -121,7 +123,7 @@ export class DevContainerConnectionProvider implements RemoteContainerConnection
121
123
  const report: RemoteStatusReport = message => progress.report({ message });
122
124
  report('Connecting to remote system...');
123
125
 
124
- const remote = await this.createContainerConnection(container, dockerConnection, devContainerConfig.name);
126
+ const remote = await this.createContainerConnection(container, dockerConnection, devContainerConfig);
125
127
  const result = await this.remoteSetup.setup({
126
128
  connection: remote,
127
129
  report,
@@ -160,13 +162,14 @@ export class DevContainerConnectionProvider implements RemoteContainerConnection
160
162
  return this.devContainerFileService.getAvailableFiles(workspacePath);
161
163
  }
162
164
 
163
- async createContainerConnection(container: Docker.Container, docker: Docker, name?: string): Promise<RemoteDockerContainerConnection> {
165
+ async createContainerConnection(container: Docker.Container, docker: Docker, config: DevContainerConfiguration): Promise<RemoteDockerContainerConnection> {
164
166
  return Promise.resolve(new RemoteDockerContainerConnection({
165
167
  id: generateUuid(),
166
- name: name ?? 'dev-container',
168
+ name: config.name ?? 'dev-container',
167
169
  type: 'Dev Container',
168
170
  docker,
169
171
  container,
172
+ config,
170
173
  }));
171
174
  }
172
175
 
@@ -190,6 +193,7 @@ export interface RemoteContainerConnectionOptions {
190
193
  type: string;
191
194
  docker: Docker;
192
195
  container: Docker.Container;
196
+ config: DevContainerConfiguration;
193
197
  }
194
198
 
195
199
  interface ContainerTerminalSession {
@@ -208,6 +212,9 @@ interface ContainerTerminalSession {
208
212
 
209
213
  export class RemoteDockerContainerConnection implements RemoteConnection {
210
214
 
215
+ @inject(ILogger) @named('dev-container')
216
+ protected readonly logger: ILogger;
217
+
211
218
  id: string;
212
219
  name: string;
213
220
  type: string;
@@ -219,6 +226,8 @@ export class RemoteDockerContainerConnection implements RemoteConnection {
219
226
 
220
227
  remoteSetupResult: RemoteSetupResult;
221
228
 
229
+ protected config: DevContainerConfiguration;
230
+
222
231
  protected activeTerminalSession: ContainerTerminalSession | undefined;
223
232
 
224
233
  protected readonly onDidDisconnectEmitter = new Emitter<void>();
@@ -232,6 +241,8 @@ export class RemoteDockerContainerConnection implements RemoteConnection {
232
241
  this.docker = options.docker;
233
242
  this.container = options.container;
234
243
 
244
+ this.config = options.config;
245
+
235
246
  this.docker.getEvents({ filters: { container: [this.container.id], event: ['stop'] } }).then(stream => {
236
247
  stream.on('data', () => this.onDidDisconnectEmitter.fire());
237
248
  });
@@ -295,6 +306,7 @@ export class RemoteDockerContainerConnection implements RemoteConnection {
295
306
  });
296
307
  const stdout = new PassThrough();
297
308
  stdout.on('data', (data: Buffer) => {
309
+ this.logger.debug('REMOTE STDOUT:', data.toString());
298
310
  if (deferred.state === 'unresolved') {
299
311
  stdoutBuffer += data.toString();
300
312
 
@@ -305,6 +317,7 @@ export class RemoteDockerContainerConnection implements RemoteConnection {
305
317
  });
306
318
  const stderr = new PassThrough();
307
319
  stderr.on('data', (data: Buffer) => {
320
+ this.logger.debug('REMOTE STDERR:', data.toString());
308
321
  if (deferred.state === 'unresolved') {
309
322
  stderrBuffer += data.toString();
310
323
 
@@ -359,13 +372,34 @@ export class RemoteDockerContainerConnection implements RemoteConnection {
359
372
  }
360
373
 
361
374
  disposeSync(): void {
362
- const remoteHost = this.getDockerHost();
363
375
  // cant use dockerrode here since this needs to happen on one tick
364
- execSync(`docker ${remoteHost}stop ${this.container.id}`);
376
+ this.shutdownContainer(true);
365
377
  }
366
378
 
367
379
  async dispose(): Promise<void> {
368
- return this.container.stop();
380
+ await this.shutdownContainer(false);
381
+ }
382
+
383
+ protected async shutdownContainer(sync: boolean): Promise<unknown> {
384
+ const remoteHost = this.getDockerHost();
385
+
386
+ const shutdownAction = this.config.shutdownAction ?? this.config.dockerComposeFile ? 'stopCompose' : 'stopContainer';
387
+
388
+ if (shutdownAction === 'stopContainer') {
389
+ return sync ? execSync(`docker ${remoteHost}stop ${this.container.id}`) : this.container.stop();
390
+ } else if (shutdownAction === 'stopCompose') {
391
+ const composeFilePath = resolveComposeFilePath(this.config);
392
+ return sync ? execSync(`docker ${remoteHost}compose -f ${composeFilePath} stop`) :
393
+ new Promise<void>((res, rej) => exec(`docker ${remoteHost}compose -f ${composeFilePath} stop`, err => {
394
+ if (err) {
395
+ console.error(err);
396
+ rej(err);
397
+ } else {
398
+ res();
399
+ }
400
+ }));
401
+ }
402
+
369
403
  }
370
404
 
371
405
  }
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=dev-container-server.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"dev-container-server.d.ts","sourceRoot":"","sources":["../../src/dev-container-server/dev-container-server.ts"],"names":[],"mappings":""}
@@ -1,48 +0,0 @@
1
- "use strict";
2
- // *****************************************************************************
3
- // Copyright (C) 2024 Typefox and others.
4
- //
5
- // This program and the accompanying materials are made available under the
6
- // terms of the Eclipse Public License v. 2.0 which is available at
7
- // http://www.eclipse.org/legal/epl-2.0.
8
- //
9
- // This Source Code may also be made available under the following Secondary
10
- // Licenses when the conditions for such availability set forth in the Eclipse
11
- // Public License v. 2.0 are satisfied: GNU General Public License, version 2
12
- // with the GNU Classpath Exception which is available at
13
- // https://www.gnu.org/software/classpath/license.html.
14
- //
15
- // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
16
- // *****************************************************************************
17
- Object.defineProperty(exports, "__esModule", { value: true });
18
- const net_1 = require("net");
19
- const process_1 = require("process");
20
- /**
21
- * this node.js Program is supposed to be executed by an docker exec session inside a docker container.
22
- * It uses a tty session to listen on stdin and send on stdout all communication with the theia backend running inside the container.
23
- */
24
- let backendPort = undefined;
25
- process_1.argv.slice(2).forEach(arg => {
26
- if (arg.startsWith('-target-port')) {
27
- backendPort = parseInt(arg.split('=')[1]);
28
- }
29
- });
30
- if (!backendPort) {
31
- throw new Error('please start with -target-port={port number}');
32
- }
33
- if (process_1.stdin.isTTY) {
34
- process_1.stdin.setRawMode(true);
35
- }
36
- const connection = (0, net_1.createConnection)(backendPort, '0.0.0.0');
37
- connection.pipe(process_1.stdout);
38
- process_1.stdin.pipe(connection);
39
- connection.on('error', error => {
40
- console.error('connection error', error);
41
- });
42
- connection.on('close', () => {
43
- console.log('connection closed');
44
- process.exit(0);
45
- });
46
- // keep the process running
47
- setInterval(() => { }, 1 << 30);
48
- //# sourceMappingURL=dev-container-server.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"dev-container-server.js","sourceRoot":"","sources":["../../src/dev-container-server/dev-container-server.ts"],"names":[],"mappings":";AAAA,gFAAgF;AAChF,yCAAyC;AACzC,EAAE;AACF,2EAA2E;AAC3E,mEAAmE;AACnE,wCAAwC;AACxC,EAAE;AACF,4EAA4E;AAC5E,8EAA8E;AAC9E,6EAA6E;AAC7E,yDAAyD;AACzD,uDAAuD;AACvD,EAAE;AACF,gFAAgF;AAChF,gFAAgF;;AAEhF,6BAAuC;AACvC,qCAA8C;AAE9C;;;GAGG;AAEH,IAAI,WAAW,GAAuB,SAAS,CAAC;AAChD,cAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE;IACxB,IAAI,GAAG,CAAC,UAAU,CAAC,cAAc,CAAC,EAAE,CAAC;QACjC,WAAW,GAAG,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC9C,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,WAAW,EAAE,CAAC;IACf,MAAM,IAAI,KAAK,CAAC,8CAA8C,CAAC,CAAC;AACpE,CAAC;AACD,IAAI,eAAK,CAAC,KAAK,EAAE,CAAC;IACd,eAAK,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;AAC3B,CAAC;AACD,MAAM,UAAU,GAAG,IAAA,sBAAgB,EAAC,WAAW,EAAE,SAAS,CAAC,CAAC;AAE5D,UAAU,CAAC,IAAI,CAAC,gBAAM,CAAC,CAAC;AACxB,eAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;AAEvB,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,KAAK,CAAC,EAAE;IAC3B,OAAO,CAAC,KAAK,CAAC,kBAAkB,EAAE,KAAK,CAAC,CAAC;AAC7C,CAAC,CAAC,CAAC;AAEH,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;IACxB,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;IACjC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACpB,CAAC,CAAC,CAAC;AAEH,2BAA2B;AAC3B,WAAW,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC"}
@@ -1,29 +0,0 @@
1
- import { AbstractRemoteRegistryContribution, RemoteRegistry } from '@theia/remote/lib/electron-browser/remote-registry-contribution';
2
- import { DevContainerFile, RemoteContainerConnectionProvider } from '../electron-common/remote-container-connection-provider';
3
- import { WorkspaceStorageService } from '@theia/workspace/lib/browser/workspace-storage-service';
4
- import { Command, MaybePromise, MessageService, QuickInputService, URI } from '@theia/core';
5
- import { WorkspaceInput, WorkspaceOpenHandlerContribution, WorkspaceService } from '@theia/workspace/lib/browser/workspace-service';
6
- import { ContainerOutputProvider } from './container-output-provider';
7
- import { WorkspaceServer } from '@theia/workspace/lib/common';
8
- import { RemotePreferences } from '@theia/remote/lib/electron-common/remote-preferences';
9
- export declare namespace RemoteContainerCommands {
10
- const REOPEN_IN_CONTAINER: Command;
11
- }
12
- export declare class ContainerConnectionContribution extends AbstractRemoteRegistryContribution implements WorkspaceOpenHandlerContribution {
13
- protected readonly connectionProvider: RemoteContainerConnectionProvider;
14
- protected readonly remotePreferences: RemotePreferences;
15
- protected readonly messageService: MessageService;
16
- protected readonly workspaceStorageService: WorkspaceStorageService;
17
- protected readonly workspaceService: WorkspaceService;
18
- protected readonly workspaceServer: WorkspaceServer;
19
- protected readonly quickInputService: QuickInputService;
20
- protected readonly containerOutputProvider: ContainerOutputProvider;
21
- registerRemoteCommands(registry: RemoteRegistry): void;
22
- canHandle(uri: URI): MaybePromise<boolean>;
23
- openWorkspace(uri: URI, options?: WorkspaceInput | undefined): Promise<void>;
24
- getWorkspaceLabel(uri: URI): Promise<string | undefined>;
25
- openInContainer(): Promise<void>;
26
- doOpenInContainer(devcontainerFile: DevContainerFile, workspacePath?: string): Promise<void>;
27
- getOrSelectDevcontainerFile(): Promise<DevContainerFile | undefined>;
28
- }
29
- //# sourceMappingURL=container-connection-contribution.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"container-connection-contribution.d.ts","sourceRoot":"","sources":["../../src/electron-browser/container-connection-contribution.ts"],"names":[],"mappings":"AAiBA,OAAO,EAAE,kCAAkC,EAAE,cAAc,EAAE,MAAM,iEAAiE,CAAC;AACrI,OAAO,EAAE,gBAAgB,EAAqB,iCAAiC,EAAE,MAAM,yDAAyD,CAAC;AACjJ,OAAO,EAAE,uBAAuB,EAAE,MAAM,wDAAwD,CAAC;AACjG,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,cAAc,EAAO,iBAAiB,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AACjG,OAAO,EAAE,cAAc,EAAE,gCAAgC,EAAE,gBAAgB,EAAE,MAAM,gDAAgD,CAAC;AACpI,OAAO,EAAE,uBAAuB,EAAE,MAAM,6BAA6B,CAAC;AACtE,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAE9D,OAAO,EAAE,iBAAiB,EAAE,MAAM,sDAAsD,CAAC;AAEzF,yBAAiB,uBAAuB,CAAC;IAC9B,MAAM,mBAAmB,SAIQ,CAAC;CAC5C;AAGD,qBACa,+BAAgC,SAAQ,kCAAmC,YAAW,gCAAgC;IAG/H,SAAS,CAAC,QAAQ,CAAC,kBAAkB,EAAE,iCAAiC,CAAC;IAGzE,SAAS,CAAC,QAAQ,CAAC,iBAAiB,EAAE,iBAAiB,CAAC;IAGxD,SAAS,CAAC,QAAQ,CAAC,cAAc,EAAE,cAAc,CAAC;IAGlD,SAAS,CAAC,QAAQ,CAAC,uBAAuB,EAAE,uBAAuB,CAAC;IAGpE,SAAS,CAAC,QAAQ,CAAC,gBAAgB,EAAE,gBAAgB,CAAC;IAGtD,SAAS,CAAC,QAAQ,CAAC,eAAe,EAAE,eAAe,CAAC;IAGpD,SAAS,CAAC,QAAQ,CAAC,iBAAiB,EAAE,iBAAiB,CAAC;IAGxD,SAAS,CAAC,QAAQ,CAAC,uBAAuB,EAAE,uBAAuB,CAAC;IAEpE,sBAAsB,CAAC,QAAQ,EAAE,cAAc,GAAG,IAAI;IAMtD,SAAS,CAAC,GAAG,EAAE,GAAG,GAAG,YAAY,CAAC,OAAO,CAAC;IAIpC,aAAa,CAAC,GAAG,EAAE,GAAG,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IAiB5E,iBAAiB,CAAC,GAAG,EAAE,GAAG,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;IAUxD,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC;IAQhC,iBAAiB,CAAC,gBAAgB,EAAE,gBAAgB,EAAE,aAAa,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAwB5F,2BAA2B,IAAI,OAAO,CAAC,gBAAgB,GAAG,SAAS,CAAC;CAyB7E"}
@@ -1,156 +0,0 @@
1
- "use strict";
2
- // *****************************************************************************
3
- // Copyright (C) 2024 Typefox and others.
4
- //
5
- // This program and the accompanying materials are made available under the
6
- // terms of the Eclipse Public License v. 2.0 which is available at
7
- // http://www.eclipse.org/legal/epl-2.0.
8
- //
9
- // This Source Code may also be made available under the following Secondary
10
- // Licenses when the conditions for such availability set forth in the Eclipse
11
- // Public License v. 2.0 are satisfied: GNU General Public License, version 2
12
- // with the GNU Classpath Exception which is available at
13
- // https://www.gnu.org/software/classpath/license.html.
14
- //
15
- // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
16
- // *****************************************************************************
17
- Object.defineProperty(exports, "__esModule", { value: true });
18
- exports.ContainerConnectionContribution = exports.RemoteContainerCommands = void 0;
19
- const tslib_1 = require("tslib");
20
- const inversify_1 = require("@theia/core/shared/inversify");
21
- const remote_registry_contribution_1 = require("@theia/remote/lib/electron-browser/remote-registry-contribution");
22
- const remote_container_connection_provider_1 = require("../electron-common/remote-container-connection-provider");
23
- const workspace_storage_service_1 = require("@theia/workspace/lib/browser/workspace-storage-service");
24
- const core_1 = require("@theia/core");
25
- const workspace_service_1 = require("@theia/workspace/lib/browser/workspace-service");
26
- const container_output_provider_1 = require("./container-output-provider");
27
- const common_1 = require("@theia/workspace/lib/common");
28
- const dev_container_workspaces_1 = require("../electron-common/dev-container-workspaces");
29
- const remote_preferences_1 = require("@theia/remote/lib/electron-common/remote-preferences");
30
- var RemoteContainerCommands;
31
- (function (RemoteContainerCommands) {
32
- RemoteContainerCommands.REOPEN_IN_CONTAINER = core_1.Command.toLocalizedCommand({
33
- id: 'dev-container:reopen-in-container',
34
- label: 'Reopen in Container',
35
- category: 'Dev Container'
36
- }, 'theia/remote/dev-container/connect');
37
- })(RemoteContainerCommands || (exports.RemoteContainerCommands = RemoteContainerCommands = {}));
38
- const LAST_USED_CONTAINER = 'lastUsedContainer';
39
- let ContainerConnectionContribution = class ContainerConnectionContribution extends remote_registry_contribution_1.AbstractRemoteRegistryContribution {
40
- registerRemoteCommands(registry) {
41
- registry.registerCommand(RemoteContainerCommands.REOPEN_IN_CONTAINER, {
42
- execute: () => this.openInContainer()
43
- });
44
- }
45
- canHandle(uri) {
46
- return uri.scheme === dev_container_workspaces_1.DEV_CONTAINER_WORKSPACE_SCHEME;
47
- }
48
- async openWorkspace(uri, options) {
49
- const filePath = new URLSearchParams(uri.query).get(dev_container_workspaces_1.DEV_CONTAINER_PATH_QUERY);
50
- if (!filePath) {
51
- throw new Error('No devcontainer file specified for workspace');
52
- }
53
- const devcontainerFiles = await this.connectionProvider.getDevContainerFiles(uri.path.toString());
54
- const devcontainerFile = devcontainerFiles.find(file => file.path === filePath);
55
- if (!devcontainerFile) {
56
- throw new Error(`Devcontainer file at ${filePath} not found in workspace`);
57
- }
58
- return this.doOpenInContainer(devcontainerFile, uri.path.toString());
59
- }
60
- async getWorkspaceLabel(uri) {
61
- const containerFilePath = new URLSearchParams(uri.query).get(dev_container_workspaces_1.DEV_CONTAINER_PATH_QUERY);
62
- if (!containerFilePath) {
63
- return;
64
- }
65
- ;
66
- const files = await this.connectionProvider.getDevContainerFiles(uri.path.toString());
67
- const devcontainerFile = files.find(file => file.path === containerFilePath);
68
- return `${uri.path.base} [Dev Container: ${devcontainerFile === null || devcontainerFile === void 0 ? void 0 : devcontainerFile.name}]`;
69
- }
70
- async openInContainer() {
71
- const devcontainerFile = await this.getOrSelectDevcontainerFile();
72
- if (!devcontainerFile) {
73
- return;
74
- }
75
- this.doOpenInContainer(devcontainerFile);
76
- }
77
- async doOpenInContainer(devcontainerFile, workspacePath) {
78
- var _a;
79
- const lastContainerInfoKey = `${LAST_USED_CONTAINER}:${devcontainerFile.path}`;
80
- const lastContainerInfo = await this.workspaceStorageService.getData(lastContainerInfoKey);
81
- this.containerOutputProvider.openChannel();
82
- const connectionResult = await this.connectionProvider.connectToContainer({
83
- nodeDownloadTemplate: this.remotePreferences['remote.nodeDownloadTemplate'],
84
- lastContainerInfo,
85
- devcontainerFile: devcontainerFile.path,
86
- workspacePath: workspacePath
87
- });
88
- this.workspaceStorageService.setData(lastContainerInfoKey, {
89
- id: connectionResult.containerId,
90
- lastUsed: Date.now()
91
- });
92
- this.workspaceServer.setMostRecentlyUsedWorkspace(`${dev_container_workspaces_1.DEV_CONTAINER_WORKSPACE_SCHEME}:${workspacePath !== null && workspacePath !== void 0 ? workspacePath : (_a = this.workspaceService.workspace) === null || _a === void 0 ? void 0 : _a.resource.path}?${dev_container_workspaces_1.DEV_CONTAINER_PATH_QUERY}=${devcontainerFile.path}`);
93
- this.openRemote(connectionResult.port, false, connectionResult.workspacePath);
94
- }
95
- async getOrSelectDevcontainerFile() {
96
- var _a;
97
- const workspace = this.workspaceService.workspace;
98
- if (!workspace) {
99
- return;
100
- }
101
- const devcontainerFiles = await this.connectionProvider.getDevContainerFiles(workspace.resource.path.toString());
102
- if (devcontainerFiles.length === 1) {
103
- return devcontainerFiles[0];
104
- }
105
- else if (devcontainerFiles.length === 0) {
106
- // eslint-disable-next-line max-len
107
- this.messageService.error(core_1.nls.localize('theia/remote/dev-container/noDevcontainerFiles', 'No devcontainer.json files found in the workspace. Please ensure you have a .devcontainer directory with a devcontainer.json file.'));
108
- return undefined;
109
- }
110
- return (_a = (await this.quickInputService.pick(devcontainerFiles.map(file => ({
111
- type: 'item',
112
- label: file.name,
113
- description: file.path,
114
- file: file,
115
- })), {
116
- title: core_1.nls.localize('theia/remote/dev-container/selectDevcontainer', 'Select a devcontainer.json file')
117
- }))) === null || _a === void 0 ? void 0 : _a.file;
118
- }
119
- };
120
- exports.ContainerConnectionContribution = ContainerConnectionContribution;
121
- tslib_1.__decorate([
122
- (0, inversify_1.inject)(remote_container_connection_provider_1.RemoteContainerConnectionProvider),
123
- tslib_1.__metadata("design:type", Object)
124
- ], ContainerConnectionContribution.prototype, "connectionProvider", void 0);
125
- tslib_1.__decorate([
126
- (0, inversify_1.inject)(remote_preferences_1.RemotePreferences),
127
- tslib_1.__metadata("design:type", Object)
128
- ], ContainerConnectionContribution.prototype, "remotePreferences", void 0);
129
- tslib_1.__decorate([
130
- (0, inversify_1.inject)(core_1.MessageService),
131
- tslib_1.__metadata("design:type", core_1.MessageService)
132
- ], ContainerConnectionContribution.prototype, "messageService", void 0);
133
- tslib_1.__decorate([
134
- (0, inversify_1.inject)(workspace_storage_service_1.WorkspaceStorageService),
135
- tslib_1.__metadata("design:type", workspace_storage_service_1.WorkspaceStorageService)
136
- ], ContainerConnectionContribution.prototype, "workspaceStorageService", void 0);
137
- tslib_1.__decorate([
138
- (0, inversify_1.inject)(workspace_service_1.WorkspaceService),
139
- tslib_1.__metadata("design:type", workspace_service_1.WorkspaceService)
140
- ], ContainerConnectionContribution.prototype, "workspaceService", void 0);
141
- tslib_1.__decorate([
142
- (0, inversify_1.inject)(common_1.WorkspaceServer),
143
- tslib_1.__metadata("design:type", Object)
144
- ], ContainerConnectionContribution.prototype, "workspaceServer", void 0);
145
- tslib_1.__decorate([
146
- (0, inversify_1.inject)(core_1.QuickInputService),
147
- tslib_1.__metadata("design:type", Object)
148
- ], ContainerConnectionContribution.prototype, "quickInputService", void 0);
149
- tslib_1.__decorate([
150
- (0, inversify_1.inject)(container_output_provider_1.ContainerOutputProvider),
151
- tslib_1.__metadata("design:type", container_output_provider_1.ContainerOutputProvider)
152
- ], ContainerConnectionContribution.prototype, "containerOutputProvider", void 0);
153
- exports.ContainerConnectionContribution = ContainerConnectionContribution = tslib_1.__decorate([
154
- (0, inversify_1.injectable)()
155
- ], ContainerConnectionContribution);
156
- //# sourceMappingURL=container-connection-contribution.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"container-connection-contribution.js","sourceRoot":"","sources":["../../src/electron-browser/container-connection-contribution.ts"],"names":[],"mappings":"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"}