@theia/remote 1.47.1 → 1.48.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 (58) hide show
  1. package/lib/electron-browser/port-forwarding/port-forwading-contribution.d.ts +6 -0
  2. package/lib/electron-browser/port-forwarding/port-forwading-contribution.d.ts.map +1 -0
  3. package/lib/electron-browser/port-forwarding/port-forwading-contribution.js +40 -0
  4. package/lib/electron-browser/port-forwarding/port-forwading-contribution.js.map +1 -0
  5. package/lib/electron-browser/port-forwarding/port-forwarding-service.d.ts +19 -0
  6. package/lib/electron-browser/port-forwarding/port-forwarding-service.d.ts.map +1 -0
  7. package/lib/electron-browser/port-forwarding/port-forwarding-service.js +76 -0
  8. package/lib/electron-browser/port-forwarding/port-forwarding-service.js.map +1 -0
  9. package/lib/electron-browser/port-forwarding/port-forwarding-widget.d.ts +17 -0
  10. package/lib/electron-browser/port-forwarding/port-forwarding-widget.d.ts.map +1 -0
  11. package/lib/electron-browser/port-forwarding/port-forwarding-widget.js +125 -0
  12. package/lib/electron-browser/port-forwarding/port-forwarding-widget.js.map +1 -0
  13. package/lib/electron-browser/remote-frontend-contribution.d.ts.map +1 -1
  14. package/lib/electron-browser/remote-frontend-contribution.js +1 -3
  15. package/lib/electron-browser/remote-frontend-contribution.js.map +1 -1
  16. package/lib/electron-browser/remote-frontend-module.d.ts +1 -0
  17. package/lib/electron-browser/remote-frontend-module.d.ts.map +1 -1
  18. package/lib/electron-browser/remote-frontend-module.js +16 -2
  19. package/lib/electron-browser/remote-frontend-module.js.map +1 -1
  20. package/lib/electron-browser/remote-registry-contribution.d.ts +1 -1
  21. package/lib/electron-browser/remote-registry-contribution.d.ts.map +1 -1
  22. package/lib/electron-browser/remote-registry-contribution.js +6 -3
  23. package/lib/electron-browser/remote-registry-contribution.js.map +1 -1
  24. package/lib/electron-common/remote-port-forwarding-provider.d.ts +11 -0
  25. package/lib/electron-common/remote-port-forwarding-provider.d.ts.map +1 -0
  26. package/lib/electron-common/remote-port-forwarding-provider.js +21 -0
  27. package/lib/electron-common/remote-port-forwarding-provider.js.map +1 -0
  28. package/lib/electron-node/remote-backend-module.d.ts.map +1 -1
  29. package/lib/electron-node/remote-backend-module.js +5 -0
  30. package/lib/electron-node/remote-backend-module.js.map +1 -1
  31. package/lib/electron-node/remote-port-forwarding-provider.d.ts +11 -0
  32. package/lib/electron-node/remote-port-forwarding-provider.d.ts.map +1 -0
  33. package/lib/electron-node/remote-port-forwarding-provider.js +53 -0
  34. package/lib/electron-node/remote-port-forwarding-provider.js.map +1 -0
  35. package/lib/electron-node/remote-types.d.ts +11 -1
  36. package/lib/electron-node/remote-types.d.ts.map +1 -1
  37. package/lib/electron-node/setup/remote-setup-service.d.ts +5 -1
  38. package/lib/electron-node/setup/remote-setup-service.d.ts.map +1 -1
  39. package/lib/electron-node/setup/remote-setup-service.js +7 -2
  40. package/lib/electron-node/setup/remote-setup-service.js.map +1 -1
  41. package/lib/electron-node/ssh/remote-ssh-connection-provider.d.ts +1 -1
  42. package/lib/electron-node/ssh/remote-ssh-connection-provider.d.ts.map +1 -1
  43. package/lib/electron-node/ssh/remote-ssh-connection-provider.js +2 -2
  44. package/lib/electron-node/ssh/remote-ssh-connection-provider.js.map +1 -1
  45. package/package.json +6 -6
  46. package/src/electron-browser/port-forwarding/port-forwading-contribution.ts +33 -0
  47. package/src/electron-browser/port-forwarding/port-forwarding-service.ts +84 -0
  48. package/src/electron-browser/port-forwarding/port-forwarding-widget.tsx +140 -0
  49. package/src/electron-browser/remote-frontend-contribution.ts +1 -3
  50. package/src/electron-browser/remote-frontend-module.ts +22 -3
  51. package/src/electron-browser/remote-registry-contribution.ts +9 -6
  52. package/src/electron-browser/style/port-forwarding-widget.css +44 -0
  53. package/src/electron-common/remote-port-forwarding-provider.ts +29 -0
  54. package/src/electron-node/remote-backend-module.ts +6 -0
  55. package/src/electron-node/remote-port-forwarding-provider.ts +50 -0
  56. package/src/electron-node/remote-types.ts +14 -1
  57. package/src/electron-node/setup/remote-setup-service.ts +12 -3
  58. package/src/electron-node/ssh/remote-ssh-connection-provider.ts +2 -2
@@ -16,8 +16,7 @@
16
16
 
17
17
  import { Command, CommandHandler, Emitter, Event } from '@theia/core';
18
18
  import { inject, injectable } from '@theia/core/shared/inversify';
19
- import { WindowService } from '@theia/core/lib/browser/window/window-service';
20
- import { WindowSearchParams } from '@theia/core/lib/common/window';
19
+ import { WindowService, WindowReloadOptions } from '@theia/core/lib/browser/window/window-service';
21
20
 
22
21
  export const RemoteRegistryContribution = Symbol('RemoteRegistryContribution');
23
22
 
@@ -33,15 +32,19 @@ export abstract class AbstractRemoteRegistryContribution implements RemoteRegist
33
32
 
34
33
  abstract registerRemoteCommands(registry: RemoteRegistry): void;
35
34
 
36
- protected openRemote(port: string, newWindow: boolean): void {
35
+ protected openRemote(port: string, newWindow: boolean, workspace?: string): void {
37
36
  const searchParams = new URLSearchParams(location.search);
38
37
  const localPort = searchParams.get('localPort') || searchParams.get('port');
39
- const options: WindowSearchParams = {
40
- port
38
+ const options: WindowReloadOptions = {
39
+ search: { port }
41
40
  };
42
41
  if (localPort) {
43
- options.localPort = localPort;
42
+ options.search!.localPort = localPort;
44
43
  }
44
+ if (workspace) {
45
+ options.hash = workspace;
46
+ }
47
+
45
48
  if (newWindow) {
46
49
  this.windowService.openNewDefaultWindow(options);
47
50
  } else {
@@ -0,0 +1,44 @@
1
+ /********************************************************************************
2
+ * Copyright (C) 2024 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
+ .port-table {
18
+ width: 100%;
19
+ margin: calc(var(--theia-ui-padding) * 2);
20
+ table-layout: fixed;
21
+ }
22
+
23
+ .port-table-header {
24
+ text-align: left;
25
+ }
26
+
27
+ .forward-port-button {
28
+ margin-left: 0;
29
+ width: 100%;
30
+ }
31
+
32
+ .button-cell {
33
+ display: flex;
34
+ padding-right: var(--theia-ui-padding);
35
+ }
36
+
37
+ .forwarded-address:hover {
38
+ cursor: pointer;
39
+ text-decoration: underline;
40
+ }
41
+
42
+ .port-edit-input-error {
43
+ outline-color: var(--theia-inputValidation-errorBorder);
44
+ }
@@ -0,0 +1,29 @@
1
+ // *****************************************************************************
2
+ // Copyright (C) 2024 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
+ export const RemoteRemotePortForwardingProviderPath = '/remote/port-forwarding';
18
+
19
+ export const RemotePortForwardingProvider = Symbol('RemoteSSHConnectionProvider');
20
+
21
+ export interface ForwardedPort {
22
+ port: number;
23
+ address?: string;
24
+ }
25
+
26
+ export interface RemotePortForwardingProvider {
27
+ forwardPort(connectionPort: number, portToForward: ForwardedPort): Promise<void>;
28
+ portRemoved(port: ForwardedPort): Promise<void>;
29
+ }
@@ -37,11 +37,17 @@ import { RemoteCopyContribution, RemoteCopyRegistry } from './setup/remote-copy-
37
37
  import { MainCopyContribution } from './setup/main-copy-contribution';
38
38
  import { RemoteNativeDependencyContribution } from './setup/remote-native-dependency-contribution';
39
39
  import { AppNativeDependencyContribution } from './setup/app-native-dependency-contribution';
40
+ import { RemotePortForwardingProviderImpl } from './remote-port-forwarding-provider';
41
+ import { RemotePortForwardingProvider, RemoteRemotePortForwardingProviderPath } from '../electron-common/remote-port-forwarding-provider';
40
42
 
41
43
  export const remoteConnectionModule = ConnectionContainerModule.create(({ bind, bindBackendService }) => {
42
44
  bind(RemoteSSHConnectionProviderImpl).toSelf().inSingletonScope();
43
45
  bind(RemoteSSHConnectionProvider).toService(RemoteSSHConnectionProviderImpl);
44
46
  bindBackendService(RemoteSSHConnectionProviderPath, RemoteSSHConnectionProvider);
47
+
48
+ bind(RemotePortForwardingProviderImpl).toSelf().inSingletonScope();
49
+ bind(RemotePortForwardingProvider).toService(RemotePortForwardingProviderImpl);
50
+ bindBackendService(RemoteRemotePortForwardingProviderPath, RemotePortForwardingProvider);
45
51
  });
46
52
 
47
53
  export default new ContainerModule((bind, _unbind, _isBound, rebind) => {
@@ -0,0 +1,50 @@
1
+ // *****************************************************************************
2
+ // Copyright (C) 2024 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 { inject, injectable } from '@theia/core/shared/inversify';
18
+ import { ForwardedPort, RemotePortForwardingProvider } from '../electron-common/remote-port-forwarding-provider';
19
+ import { createServer, Server } from 'net';
20
+ import { RemoteConnectionService } from './remote-connection-service';
21
+
22
+ @injectable()
23
+ export class RemotePortForwardingProviderImpl implements RemotePortForwardingProvider {
24
+
25
+ @inject(RemoteConnectionService)
26
+ protected readonly connectionService: RemoteConnectionService;
27
+
28
+ protected forwardedPorts: Map<number, Server> = new Map();
29
+
30
+ async forwardPort(connectionPort: number, portToForward: ForwardedPort): Promise<void> {
31
+ const currentConnection = this.connectionService.getConnectionFromPort(connectionPort);
32
+ if (!currentConnection) {
33
+ throw new Error(`No connection found for port ${connectionPort}`);
34
+ }
35
+
36
+ const server = createServer(socket => {
37
+ currentConnection?.forwardOut(socket, portToForward.port);
38
+ }).listen(portToForward.port, portToForward.address);
39
+ this.forwardedPorts.set(portToForward.port, server);
40
+ }
41
+
42
+ async portRemoved(forwardedPort: ForwardedPort): Promise<void> {
43
+ const proxy = this.forwardedPorts.get(forwardedPort.port);
44
+ if (proxy) {
45
+ proxy.close();
46
+ this.forwardedPorts.delete(forwardedPort.port);
47
+ }
48
+ }
49
+
50
+ }
@@ -49,8 +49,21 @@ export interface RemoteConnection extends Disposable {
49
49
  localPort: number;
50
50
  remotePort: number;
51
51
  onDidDisconnect: Event<void>;
52
- forwardOut(socket: net.Socket): void;
52
+ forwardOut(socket: net.Socket, port?: number): void;
53
+
54
+ /**
55
+ * execute a single command on the remote machine
56
+ */
53
57
  exec(cmd: string, args?: string[], options?: RemoteExecOptions): Promise<RemoteExecResult>;
58
+
59
+ /**
60
+ * execute a command on the remote machine and wait for a specific output
61
+ * @param tester function which returns true if the output is as expected
62
+ */
54
63
  execPartial(cmd: string, tester: RemoteExecTester, args?: string[], options?: RemoteExecOptions): Promise<RemoteExecResult>;
64
+
65
+ /**
66
+ * copy files from local to remote
67
+ */
55
68
  copy(localPath: string | Buffer | NodeJS.ReadableStream, remotePath: string): Promise<void>;
56
69
  }
@@ -29,6 +29,11 @@ export interface RemoteSetupOptions {
29
29
  nodeDownloadTemplate?: string;
30
30
  }
31
31
 
32
+ export interface RemoteSetupResult {
33
+ applicationDirectory: string;
34
+ nodeDirectory: string;
35
+ }
36
+
32
37
  @injectable()
33
38
  export class RemoteSetupService {
34
39
 
@@ -47,7 +52,7 @@ export class RemoteSetupService {
47
52
  @inject(ApplicationPackage)
48
53
  protected readonly applicationPackage: ApplicationPackage;
49
54
 
50
- async setup(options: RemoteSetupOptions): Promise<void> {
55
+ async setup(options: RemoteSetupOptions): Promise<RemoteSetupResult> {
51
56
  const {
52
57
  connection,
53
58
  report,
@@ -86,12 +91,16 @@ export class RemoteSetupService {
86
91
  report('Starting application on remote...');
87
92
  const port = await this.startApplication(connection, platform, applicationDirectory, remoteNodeDirectory);
88
93
  connection.remotePort = port;
94
+ return {
95
+ applicationDirectory: libDir,
96
+ nodeDirectory: remoteNodeDirectory
97
+ };
89
98
  }
90
99
 
91
100
  protected async startApplication(connection: RemoteConnection, platform: RemotePlatform, remotePath: string, nodeDir: string): Promise<number> {
92
101
  const nodeExecutable = this.scriptService.joinPath(platform, nodeDir, ...(platform.os === OS.Type.Windows ? ['node.exe'] : ['bin', 'node']));
93
102
  const mainJsFile = this.scriptService.joinPath(platform, remotePath, 'lib', 'backend', 'main.js');
94
- const localAddressRegex = /listening on http:\/\/127.0.0.1:(\d+)/;
103
+ const localAddressRegex = /listening on http:\/\/0.0.0.0:(\d+)/;
95
104
  let prefix = '';
96
105
  if (platform.os === OS.Type.Windows) {
97
106
  // We might to switch to PowerShell beforehand on Windows
@@ -101,7 +110,7 @@ export class RemoteSetupService {
101
110
  // This way, our current working directory is set as expected
102
111
  const result = await connection.execPartial(`${prefix}cd "${remotePath}";${nodeExecutable}`,
103
112
  stdout => localAddressRegex.test(stdout),
104
- [mainJsFile, '--hostname=127.0.0.1', '--port=0', '--remote']);
113
+ [mainJsFile, '--hostname=0.0.0.0', `--port=${connection.remotePort ?? 0}`, '--remote']);
105
114
 
106
115
  const match = localAddressRegex.exec(result.stdout);
107
116
  if (!match) {
@@ -278,8 +278,8 @@ export class RemoteSSHConnection implements RemoteConnection {
278
278
  return sftpClient;
279
279
  }
280
280
 
281
- forwardOut(socket: net.Socket): void {
282
- this.client.forwardOut(socket.localAddress!, socket.localPort!, '127.0.0.1', this.remotePort, (err, stream) => {
281
+ forwardOut(socket: net.Socket, port?: number): void {
282
+ this.client.forwardOut(socket.localAddress!, socket.localPort!, '127.0.0.1', port ?? this.remotePort, (err, stream) => {
283
283
  if (err) {
284
284
  console.debug('Proxy message rejected', err);
285
285
  } else {