Initialize remote IDE scaffold

This commit is contained in:
2026-05-10 14:08:25 +00:00
commit 138eea3231
97 changed files with 21129 additions and 0 deletions
@@ -0,0 +1,16 @@
appId: global.foss.git-zone.ide
productName: Git.Zone IDE
directories:
output: dist
files:
- dist_ts/**/*
- package.json
linux:
target:
- AppImage
mac:
target:
- dmg
win:
target:
- nsis
+22
View File
@@ -0,0 +1,22 @@
{
"name": "@git.zone/ide-electron-shell",
"version": "0.1.0",
"private": true,
"type": "module",
"main": "dist_ts/main.js",
"scripts": {
"build": "tsc -p tsconfig.json",
"start": "pnpm run build && electron dist_ts/main.js",
"package": "pnpm run build && electron-builder --config electron-builder.yml"
},
"dependencies": {
"@git.zone/ide-protocol": "workspace:*",
"@git.zone/ide-server-installer": "workspace:*",
"@git.zone/ide-ssh": "workspace:*",
"electron": "^42.0.1"
},
"devDependencies": {
"electron-builder": "^26.8.1"
},
"files": ["dist_ts/**/*", "electron-builder.yml"]
}
+186
View File
@@ -0,0 +1,186 @@
import type { IIdeSshTarget } from '@git.zone/ide-protocol';
import * as plugins from './plugins.js';
const defaultRemoteTheiaPort = 33990;
const defaultOpenCodePort = 4096;
class GitZoneIdeElectronShell {
private readonly tunnels: plugins.ideSsh.ISshTunnelHandle[] = [];
async start() {
await plugins.electron.app.whenReady();
this.registerIpcHandlers();
const remoteUrl = getArgValue('--remote-url');
if (remoteUrl) {
this.openWorkspaceWindow(remoteUrl);
} else {
await this.openLauncherWindow();
}
plugins.electron.app.on('activate', async () => {
if (plugins.electron.BrowserWindow.getAllWindows().length === 0) {
await this.openLauncherWindow();
}
});
plugins.electron.app.on('before-quit', () => {
for (const tunnel of this.tunnels) {
void tunnel.dispose();
}
});
}
private registerIpcHandlers() {
plugins.electron.ipcMain.handle('gitzone:list-hosts', async () => {
const hosts = await plugins.ideSsh.readSshConfig();
return plugins.ideSsh.listConnectableHosts(hosts).map((host) => ({
alias: host.alias,
hostName: host.hostName,
user: host.user,
port: host.port,
}));
});
plugins.electron.ipcMain.handle('gitzone:connect', async (_event, input: IConnectInput) => {
const localPort = await plugins.ideSsh.findFreePort();
const target: IIdeSshTarget = {
id: input.hostAlias,
hostAlias: input.hostAlias,
workspacePath: input.workspacePath,
};
const opencodePassword = plugins.crypto.randomBytes(24).toString('base64url');
const remoteTheiaPort = input.remoteTheiaPort ?? defaultRemoteTheiaPort;
const opencodePort = input.openCodePort ?? defaultOpenCodePort;
const bootstrapCommand = plugins.ideServerInstaller.createRemoteBootstrapCommand({
serverVersion: plugins.electron.app.getVersion(),
workspacePath: input.workspacePath,
theiaPort: remoteTheiaPort,
opencodePort,
opencodeUsername: 'opencode',
opencodePassword,
});
const bootstrapResult = await plugins.ideSsh.runSshCommand(target, bootstrapCommand, {
timeoutMs: 30000,
batchMode: input.batchMode ?? true,
});
if (bootstrapResult.exitCode !== 0) {
throw new Error(bootstrapResult.stderr || `Remote bootstrap failed with ${bootstrapResult.exitCode}`);
}
const tunnel = plugins.ideSsh.startSshTunnel(target, {
localPort,
remotePort: remoteTheiaPort,
batchMode: input.batchMode ?? true,
});
this.tunnels.push(tunnel);
const url = `http://127.0.0.1:${localPort}`;
this.openWorkspaceWindow(url);
return { url, localPort, remoteTheiaPort, opencodePort };
});
}
private async openLauncherWindow() {
const window = new plugins.electron.BrowserWindow({
width: 960,
height: 720,
title: 'Git.Zone IDE',
webPreferences: {
contextIsolation: false,
nodeIntegration: true,
},
});
await window.loadURL(`data:text/html;charset=utf-8,${encodeURIComponent(renderLauncherHtml())}`);
}
private openWorkspaceWindow(url: string) {
const window = new plugins.electron.BrowserWindow({
width: 1440,
height: 960,
title: 'Git.Zone IDE',
webPreferences: {
contextIsolation: true,
nodeIntegration: false,
},
});
void window.loadURL(url);
}
}
interface IConnectInput {
hostAlias: string;
workspacePath: string;
remoteTheiaPort?: number;
openCodePort?: number;
batchMode?: boolean;
}
const getArgValue = (name: string) => {
const index = process.argv.indexOf(name);
if (index === -1) {
return undefined;
}
return process.argv[index + 1];
};
const renderLauncherHtml = () => `<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<title>Git.Zone IDE</title>
<style>
body { margin: 0; font: 14px system-ui, sans-serif; background: #111827; color: #f9fafb; }
main { max-width: 720px; margin: 72px auto; padding: 32px; background: #1f2937; border-radius: 16px; }
h1 { margin-top: 0; font-size: 32px; }
label { display: block; margin-top: 18px; color: #d1d5db; }
input, select, button { width: 100%; box-sizing: border-box; margin-top: 8px; padding: 12px; border-radius: 10px; border: 1px solid #4b5563; background: #111827; color: #f9fafb; }
button { margin-top: 24px; background: #22c55e; border: 0; color: #052e16; font-weight: 700; cursor: pointer; }
pre { white-space: pre-wrap; color: #fca5a5; }
</style>
</head>
<body>
<main>
<h1>Git.Zone IDE</h1>
<p>Connect to an SSH host and open a remote Theia workspace powered by OpenCode server.</p>
<label>SSH Host</label>
<select id="host"></select>
<label>Remote Workspace Path</label>
<input id="workspace" value="$HOME" />
<label>Remote Theia Port</label>
<input id="theiaPort" value="${defaultRemoteTheiaPort}" />
<label>OpenCode Port</label>
<input id="opencodePort" value="${defaultOpenCodePort}" />
<button id="connect">Connect</button>
<pre id="output"></pre>
</main>
<script>
const { ipcRenderer } = require('electron');
const hostSelect = document.getElementById('host');
const output = document.getElementById('output');
ipcRenderer.invoke('gitzone:list-hosts').then((hosts) => {
for (const host of hosts) {
const option = document.createElement('option');
option.value = host.alias;
option.textContent = host.alias + (host.hostName ? ' (' + host.hostName + ')' : '');
hostSelect.appendChild(option);
}
}).catch((error) => output.textContent = error.stack || String(error));
document.getElementById('connect').addEventListener('click', async () => {
output.textContent = 'Connecting...';
try {
const result = await ipcRenderer.invoke('gitzone:connect', {
hostAlias: hostSelect.value,
workspacePath: document.getElementById('workspace').value,
remoteTheiaPort: Number(document.getElementById('theiaPort').value),
openCodePort: Number(document.getElementById('opencodePort').value),
});
output.textContent = 'Opened ' + result.url;
} catch (error) {
output.textContent = error.stack || String(error);
}
});
</script>
</body>
</html>`;
void new GitZoneIdeElectronShell().start();
@@ -0,0 +1,6 @@
import * as crypto from 'node:crypto';
import * as electron from 'electron';
import * as ideServerInstaller from '@git.zone/ide-server-installer';
import * as ideSsh from '@git.zone/ide-ssh';
export { crypto, electron, ideServerInstaller, ideSsh };
+11
View File
@@ -0,0 +1,11 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"rootDir": "ts",
"outDir": "dist_ts",
"declaration": true,
"declarationMap": true,
"sourceMap": true
},
"include": ["ts/**/*.ts"]
}
@@ -0,0 +1,295 @@
/**
* Don't touch this file. It will be regenerated by theia build.
* To customize webpack configuration change /mnt/data/foss.global/git.zone/ide/applications/remote-theia/webpack.config.js
*/
// @ts-check
const path = require('path');
const webpack = require('webpack');
const yargs = require('yargs');
const resolvePackagePath = require('resolve-package-path');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const CompressionPlugin = require('compression-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const { MonacoWebpackPlugin } = require('@theia/native-webpack-plugin/lib/monaco-webpack-plugins.js');
const outputPath = path.resolve(__dirname, 'lib', 'frontend');
const { mode, staticCompression } = yargs.option('mode', {
description: "Mode to use",
choices: ["development", "production"],
default: "production"
}).option('static-compression', {
description: 'Controls whether to enable compression of static artifacts.',
type: 'boolean',
default: true
}).argv;
const development = mode === 'development';
const plugins = [
new CopyWebpackPlugin({
patterns: [
{
// copy secondary window html file to lib folder
from: path.resolve(__dirname, 'src-gen/frontend/secondary-window.html')
},
{
// copy webview files to lib folder
from: path.join(resolvePackagePath('@theia/plugin-ext', __dirname), '..', 'src', 'main', 'browser', 'webview', 'pre'),
to: path.resolve(__dirname, 'lib', 'webview', 'pre')
}
,
{
// copy frontend plugin host files
from: path.join(resolvePackagePath('@theia/plugin-ext-vscode', __dirname), '..', 'lib', 'node', 'context', 'plugin-vscode-init-fe.js'),
to: path.resolve(__dirname, 'lib', 'frontend', 'context', 'plugin-vscode-init-fe.js')
}
,
{
// copy shell integration scripts
from: path.join(resolvePackagePath('@theia/terminal', __dirname), '..', 'src', 'node', 'shell-integrations'),
to: path.resolve(__dirname, 'lib', 'backend', 'shell-integrations')
}
]
}),
new webpack.ProvidePlugin({
// the Buffer class doesn't exist in the browser but some dependencies rely on it
Buffer: ['buffer', 'Buffer']
}),
new MonacoWebpackPlugin()
];
// it should go after copy-plugin in order to compress monaco as well
if (staticCompression) {
plugins.push(new CompressionPlugin({}));
}
module.exports = [{
mode,
plugins,
devtool: 'source-map',
entry: {
bundle: path.resolve(__dirname, 'src-gen/frontend/index.js'),
},
output: {
filename: '[name].js',
path: outputPath,
devtoolModuleFilenameTemplate: 'webpack:///[resource-path]?[loaders]',
globalObject: 'self'
},
target: 'web',
cache: staticCompression,
module: {
rules: [
{
test: /\.css$/,
exclude: /materialcolors\.css$|\.useable\.css$/,
use: ['style-loader', 'css-loader']
},
{
test: /materialcolors\.css$|\.useable\.css$/,
use: [
{
loader: 'style-loader',
options: {
esModule: false,
injectType: 'lazySingletonStyleTag',
attributes: {
id: 'theia-theme'
}
}
},
'css-loader'
]
},
{
test: /\.(ttf|eot|svg)(\?v=\d+\.\d+\.\d+)?$/,
type: 'asset',
parser: {
dataUrlCondition: {
maxSize: 10000,
}
},
generator: {
dataUrl: {
mimetype: 'image/svg+xml'
}
}
},
{
test: /\.(jpg|png|gif)$/,
type: 'asset/resource',
generator: {
filename: '[hash].[ext]'
}
},
{
// see https://github.com/eclipse-theia/theia/issues/556
test: /source-map-support/,
loader: 'ignore-loader'
},
{
test: /\.d\.ts$/,
loader: 'ignore-loader'
},
{
test: /\.js$/,
enforce: 'pre',
loader: 'source-map-loader',
exclude: /jsonc-parser|fast-plist|onigasm/
},
{
test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/,
type: 'asset',
parser: {
dataUrlCondition: {
maxSize: 10000,
}
},
generator: {
dataUrl: {
mimetype: 'image/svg+xml'
}
}
},
{
test: /node_modules[\\|/](vscode-languageserver-types|vscode-uri|jsonc-parser|vscode-languageserver-protocol)/,
loader: 'umd-compat-loader'
},
{
test: /\.wasm$/,
type: 'asset/resource'
},
{
test: /\.plist$/,
type: 'asset/resource'
}
]
},
resolve: {
fallback: {
'child_process': false,
'crypto': false,
'net': false,
'path': require.resolve('path-browserify'),
'process': false,
'os': false,
'timers': false
},
alias: {
// Replace Monaco's nls module with Theia's localization-aware version.
// ESM exports are immutable so we cannot override localize/localize2 at runtime.
// Using the resolved absolute path ensures that both external imports
// (e.g. '@theia/monaco-editor-core/esm/vs/nls') and internal relative
// imports within Monaco (e.g. '../nls.js') are redirected.
[path.join(resolvePackagePath('@theia/monaco-editor-core', __dirname), '..', 'esm', 'vs', 'nls.js')]:
path.join(resolvePackagePath('@theia/monaco', __dirname), '..', 'lib', 'browser', 'monaco-nls.js')
},
extensions: ['.js']
},
stats: {
warnings: true,
children: true
},
ignoreWarnings: [
// Some packages do not have source maps, that's ok
/Failed to parse source map/,
{
// Monaco uses 'require' in a non-standard way
module: /@theia\/monaco-editor-core/,
message: /require function is used in a way in which dependencies cannot be statically extracted/
}
]
},
{
// The Monaco editor worker must be built separately without the NLS alias.
// The NLS alias redirects to monaco-nls.ts which imports from @theia/core,
// and those modules are not available in the web worker context.
mode,
devtool: 'source-map',
entry: {
'editor.worker': '@theia/monaco-editor-core/esm/vs/editor/common/services/editorWebWorkerMain.js'
},
output: {
filename: '[name].js',
path: outputPath,
devtoolModuleFilenameTemplate: 'webpack:///[resource-path]?[loaders]',
globalObject: 'self'
},
target: 'webworker',
cache: staticCompression,
resolve: {
extensions: ['.js']
},
ignoreWarnings: [
{
module: /@theia\/monaco-editor-core/,
message: /require function is used in a way in which dependencies cannot be statically extracted/
}
]
},
{
mode,
plugins: [
new MiniCssExtractPlugin({
// Options similar to the same options in webpackOptions.output
// both options are optional
filename: "[name].css",
chunkFilename: "[id].css",
}),
new MonacoWebpackPlugin(),
],
devtool: 'source-map',
entry: {
"secondary-window": path.resolve(__dirname, 'src-gen/frontend/secondary-index.js'),
},
output: {
filename: '[name].js',
path: outputPath,
devtoolModuleFilenameTemplate: 'webpack:///[resource-path]?[loaders]',
globalObject: 'self'
},
target: 'web',
cache: staticCompression,
module: {
rules: [
{
test: /.css$/i,
use: [MiniCssExtractPlugin.loader, "css-loader"]
},
{
test: /.wasm$/,
type: 'asset/resource'
}
]
},
resolve: {
fallback: {
'child_process': false,
'crypto': false,
'net': false,
'path': require.resolve('path-browserify'),
'process': false,
'os': false,
'timers': false
},
alias: {
// Replace Monaco's nls module with Theia's localization-aware version.
// ESM exports are immutable so we cannot override localize/localize2 at runtime.
// Using the resolved absolute path ensures that both external imports
// (e.g. '@theia/monaco-editor-core/esm/vs/nls') and internal relative
// imports within Monaco (e.g. '../nls.js') are redirected.
[path.join(resolvePackagePath('@theia/monaco-editor-core', __dirname), '..', 'esm', 'vs', 'nls.js')]:
path.join(resolvePackagePath('@theia/monaco', __dirname), '..', 'lib', 'browser', 'monaco-nls.js')
},
extensions: ['.js']
},
stats: {
warnings: true,
children: true
},
ignoreWarnings: [
{
// Monaco uses 'require' in a non-standard way
module: /@theia\/monaco-editor-core/,
message: /require function is used in a way in which dependencies cannot be statically extracted/
}
]
}];
@@ -0,0 +1,183 @@
/**
* Don't touch this file. It will be regenerated by theia build.
* To customize webpack configuration change /mnt/data/foss.global/git.zone/ide/applications/remote-theia/webpack.config.js
*/
// @ts-check
const path = require('path');
const yargs = require('yargs');
const webpack = require('webpack');
const TerserPlugin = require('terser-webpack-plugin');
const NativeWebpackPlugin = require('@theia/native-webpack-plugin');
const { MonacoWebpackPlugin } = require('@theia/native-webpack-plugin/lib/monaco-webpack-plugins.js');
const { mode } = yargs.option('mode', {
description: "Mode to use",
choices: ["development", "production"],
default: "production"
}).argv;
const production = mode === 'production';
/** @type {import('webpack').EntryObject} */
const commonJsLibraries = {};
for (const [entryPointName, entryPointPath] of Object.entries({
'backend-init-theia': '@theia/plugin-ext/lib/hosted/node/scanners/backend-init-theia',
'parcel-watcher': '@theia/filesystem/lib/node/parcel-watcher',
'plugin-vscode-init': '@theia/plugin-ext-vscode/lib/node/plugin-vscode-init',
})) {
commonJsLibraries[entryPointName] = {
import: require.resolve(entryPointPath),
library: {
type: 'commonjs2',
},
};
}
const ignoredResources = new Set();
if (process.platform !== 'win32') {
ignoredResources.add('@vscode/windows-ca-certs');
ignoredResources.add('@vscode/windows-ca-certs/build/Release/crypt32.node');
}
const nativePlugin = new NativeWebpackPlugin({
out: 'native',
trash: true,
ripgrep: true,
pty: true,
nativeBindings: {
drivelist: 'drivelist/build/Release/drivelist.node'
}
});
// Ensure that node-pty is correctly hoisted
try {
require.resolve('node-pty');
} catch {
console.error('"node-pty" dependency is not installed correctly. Ensure that it is available in the root node_modules directory.');
console.error('Exiting webpack build process.');
process.exit(1);
}
/** @type {import('webpack').Configuration} */
const config = {
mode,
devtool: mode === 'development' ? 'source-map' : false,
target: 'node',
node: {
global: false,
__filename: false,
__dirname: false
},
resolve: {
extensions: ['.js', '.json', '.wasm', '.node'],
},
output: {
filename: '[name].js',
path: path.resolve(__dirname, 'lib', 'backend'),
devtoolModuleFilenameTemplate: 'webpack:///[absolute-resource-path]?[loaders]',
},
entry: {
// Main entry point of the Theia application backend:
'main': require.resolve('./src-gen/backend/main'),
// Theia's IPC mechanism:
'ipc-bootstrap': require.resolve('@theia/core/lib/node/messaging/ipc-bootstrap'),
// VS Code extension support:
'plugin-host': require.resolve('@theia/plugin-ext/lib/hosted/node/plugin-host'),
// Make sure the node-pty thread workers can be executed:
'worker/conoutSocketWorker': require.resolve('node-pty/lib/worker/conoutSocketWorker'),
'conpty_console_list_agent': require.resolve('node-pty/lib/conpty_console_list_agent'),
...commonJsLibraries
},
module: {
rules: [
// Make sure we can still find and load our native addons.
{
test: /\.node$/,
loader: 'node-loader',
options: {
name: 'native/[name].[ext]'
}
},
{
test: /\.d\.ts$/,
loader: 'ignore-loader'
},
{
test: /\.js$/,
enforce: 'pre',
loader: 'source-map-loader'
},
// node-pty uses a dynamic require which needs to be rewritten to work with webpack.
{
test: /node_modules[/\\]node-pty[/\\]lib[/\\]utils.js$/,
loader: 'string-replace-loader',
options: {
search: /require\(/,
replace: '__non_webpack_require__(',
flags: 'g'
}
},
// jsonc-parser exposes its UMD implementation by default, which
// confuses Webpack leading to missing js in the bundles.
{
test: /node_modules[\/](jsonc-parser)/,
loader: 'umd-compat-loader'
}
]
},
plugins: [
// Some native dependencies need special handling
nativePlugin,
// Optional node dependencies can be safely ignored
new webpack.IgnorePlugin({
checkResource: resource => ignoredResources.has(resource)
}),
new MonacoWebpackPlugin()
],
optimization: {
// Split and reuse code across the various entry points
splitChunks: {
chunks: 'all'
},
// Only minimize if we run webpack in production mode
minimize: production,
minimizer: [
new TerserPlugin({
exclude: /^(lib|builtins)\//
})
]
},
ignoreWarnings: [
// Some packages do not have source maps, that's ok
/Failed to parse source map/,
// require with expressions are not supported
/the request of a dependency is an expression/,
// Some packages use dynamic requires, we can safely ignore them (they are handled by the native webpack plugin)
/require function is used in a way in which dependencies cannot be statically extracted/, {
module: /yargs/
}, {
module: /node-pty/
}, {
module: /require-main-filename/
}, {
module: /ws/
}, {
module: /express/
}, {
module: /cross-spawn/
}, {
module: /@parcel\/watcher/
}
]
};
module.exports = {
config,
nativePlugin,
ignoredResources
};
+49
View File
@@ -0,0 +1,49 @@
{
"name": "@git.zone/ide-remote-theia",
"version": "0.1.0",
"private": true,
"scripts": {
"build": "pnpm run rebuild && theia build --mode development",
"rebuild": "theia rebuild:browser --cacheRoot ../..",
"start": "theia start",
"watch": "pnpm run rebuild && theia build --watch --mode development"
},
"dependencies": {
"@git.zone/ide-extension-opencode": "workspace:*",
"@git.zone/ide-extension-product": "workspace:*",
"@git.zone/ide-extension-remote": "workspace:*",
"@theia/core": "1.71.0",
"@theia/editor": "1.71.0",
"@theia/filesystem": "1.71.0",
"@theia/markers": "1.71.0",
"@theia/messages": "1.71.0",
"@theia/monaco": "1.71.0",
"@theia/monaco-editor-core": "1.108.201",
"@theia/navigator": "1.71.0",
"@theia/output": "1.71.0",
"@theia/plugin-ext": "1.71.0",
"@theia/plugin-ext-vscode": "1.71.0",
"@theia/preferences": "1.71.0",
"@theia/process": "1.71.0",
"@theia/scm": "1.71.0",
"@theia/search-in-workspace": "1.71.0",
"@theia/task": "1.71.0",
"@theia/terminal": "1.71.0",
"@theia/vsx-registry": "1.71.0",
"@theia/workspace": "1.71.0"
},
"devDependencies": {
"@theia/cli": "1.71.0",
"source-map-loader": "^5.0.0",
"string-replace-loader": "^3.3.0"
},
"theia": {
"target": "browser",
"frontend": {
"config": {
"applicationName": "Git.Zone IDE",
"preferencesDirName": ".git-zone-ide"
}
}
}
}
@@ -0,0 +1,174 @@
// @ts-check
const { performance } = require('perf_hooks');
const startupLog = (milestone) => console.debug(`Backend main: ${milestone} [${(performance.now() / 1000).toFixed(3)} s since backend process start]`);
startupLog('entry point loaded');
const { BackendApplicationConfigProvider } = require('@theia/core/lib/node/backend-application-config-provider');
const main = require('@theia/core/lib/node/main');
BackendApplicationConfigProvider.set({
"singleInstance": true,
"frontendConnectionTimeout": 0,
"configurationFolder": ".theia"
});
globalThis.extensionInfo = [
{
"name": "@theia/core",
"version": "1.71.0"
},
{
"name": "@git.zone/ide-extension-opencode",
"version": "0.1.0"
},
{
"name": "@git.zone/ide-extension-product",
"version": "0.1.0"
},
{
"name": "@git.zone/ide-extension-remote",
"version": "0.1.0"
},
{
"name": "@theia/variable-resolver",
"version": "1.71.0"
},
{
"name": "@theia/editor",
"version": "1.71.0"
},
{
"name": "@theia/filesystem",
"version": "1.71.0"
},
{
"name": "@theia/workspace",
"version": "1.71.0"
},
{
"name": "@theia/markers",
"version": "1.71.0"
},
{
"name": "@theia/messages",
"version": "1.71.0"
},
{
"name": "@theia/outline-view",
"version": "1.71.0"
},
{
"name": "@theia/monaco",
"version": "1.71.0"
},
{
"name": "@theia/navigator",
"version": "1.71.0"
},
{
"name": "@theia/output",
"version": "1.71.0"
},
{
"name": "@theia/ai-core",
"version": "1.71.0"
},
{
"name": "@theia/ai-mcp",
"version": "1.71.0"
},
{
"name": "@theia/bulk-edit",
"version": "1.71.0"
},
{
"name": "@theia/callhierarchy",
"version": "1.71.0"
},
{
"name": "@theia/console",
"version": "1.71.0"
},
{
"name": "@theia/process",
"version": "1.71.0"
},
{
"name": "@theia/file-search",
"version": "1.71.0"
},
{
"name": "@theia/terminal",
"version": "1.71.0"
},
{
"name": "@theia/userstorage",
"version": "1.71.0"
},
{
"name": "@theia/preferences",
"version": "1.71.0"
},
{
"name": "@theia/terminal-manager",
"version": "1.71.0"
},
{
"name": "@theia/task",
"version": "1.71.0"
},
{
"name": "@theia/test",
"version": "1.71.0"
},
{
"name": "@theia/debug",
"version": "1.71.0"
},
{
"name": "@theia/editor-preview",
"version": "1.71.0"
},
{
"name": "@theia/notebook",
"version": "1.71.0"
},
{
"name": "@theia/scm",
"version": "1.71.0"
},
{
"name": "@theia/search-in-workspace",
"version": "1.71.0"
},
{
"name": "@theia/timeline",
"version": "1.71.0"
},
{
"name": "@theia/typehierarchy",
"version": "1.71.0"
},
{
"name": "@theia/plugin-ext",
"version": "1.71.0"
},
{
"name": "@theia/plugin-ext-vscode",
"version": "1.71.0"
},
{
"name": "@theia/vsx-registry",
"version": "1.71.0"
}
];
const serverModule = require('./server');
const serverAddress = main.start(serverModule());
serverAddress.then((addressInfo) => {
if (process && process.send && addressInfo) {
process.send(addressInfo);
}
});
globalThis.serverAddress = serverAddress;
@@ -0,0 +1,102 @@
// @ts-check
require('reflect-metadata');
const { performance } = require('perf_hooks');
const startupLog = (milestone) => console.debug(`Backend server: ${milestone} [${(performance.now() / 1000).toFixed(3)} s since backend process start]`);
startupLog('loading modules...');
// Erase the ELECTRON_RUN_AS_NODE variable from the environment, else Electron apps started using Theia will pick it up.
if ('ELECTRON_RUN_AS_NODE' in process.env) {
delete process.env.ELECTRON_RUN_AS_NODE;
}
const path = require('path');
process.env.THEIA_APP_PROJECT_PATH = path.resolve(__dirname, '..', '..')
const express = require('@theia/core/shared/express');
const { Container } = require('@theia/core/shared/inversify');
const { BackendApplication, BackendApplicationServer, CliManager } = require('@theia/core/lib/node');
const { backendApplicationModule } = require('@theia/core/lib/node/backend-application-module');
const { messagingBackendModule } = require('@theia/core/lib/node/messaging/messaging-backend-module');
const { loggerBackendModule } = require('@theia/core/lib/node/logger-backend-module');
const container = new Container();
container.load(backendApplicationModule);
container.load(messagingBackendModule);
container.load(loggerBackendModule);
startupLog('container created');
function defaultServeStatic(app) {
app.use(express.static(path.resolve(__dirname, '../../lib/frontend')))
}
function load(raw) {
return Promise.resolve(raw).then(
module => container.load(module.default)
);
}
async function start(port, host, argv = process.argv) {
if (!container.isBound(BackendApplicationServer)) {
container.bind(BackendApplicationServer).toConstantValue({ configure: defaultServeStatic });
}
let result = undefined;
await container.get(CliManager).initializeCli(argv.slice(2),
() => {
startupLog('resolving application');
const application = container.get(BackendApplication);
startupLog('application resolved');
return application.configured;
},
async () => {
result = container.get(BackendApplication).start(port, host);
});
if (result) {
return result;
} else {
return Promise.reject(0);
}
}
module.exports = async (port, host, argv) => {
try {
await load(require('@theia/core/lib/node/i18n/i18n-backend-module'));
await load(require('@theia/core/lib/node/hosting/backend-hosting-module'));
await load(require('@theia/core/lib/node/request/backend-request-module'));
await load(require('@git.zone/ide-extension-opencode/lib/node/gitzone-opencode-backend-module'));
await load(require('@git.zone/ide-extension-remote/lib/node/gitzone-remote-backend-module'));
await load(require('@theia/editor/lib/node/editor-backend-module'));
await load(require('@theia/filesystem/lib/node/filesystem-backend-module'));
await load(require('@theia/filesystem/lib/node/download/file-download-backend-module'));
await load(require('@theia/workspace/lib/node/workspace-backend-module'));
await load(require('@theia/markers/lib/node/problem-backend-module'));
await load(require('@theia/messages/lib/node/messages-backend-module'));
await load(require('@theia/navigator/lib/node/navigator-backend-module'));
await load(require('@theia/output/lib/node/output-backend-module'));
await load(require('@theia/ai-core/lib/node/ai-core-backend-module'));
await load(require('@theia/ai-mcp/lib/node/mcp-backend-module'));
await load(require('@theia/process/lib/common/process-common-module'));
await load(require('@theia/process/lib/node/process-backend-module'));
await load(require('@theia/file-search/lib/node/file-search-backend-module'));
await load(require('@theia/terminal/lib/node/terminal-backend-module'));
await load(require('@theia/preferences/lib/node/preference-backend-module'));
await load(require('@theia/task/lib/node/task-backend-module'));
await load(require('@theia/test/lib/node/test-backend-module'));
await load(require('@theia/debug/lib/node/debug-backend-module'));
await load(require('@theia/editor-preview/lib/node/editor-preview-backend-module'));
await load(require('@theia/notebook/lib/node/notebook-backend-module'));
await load(require('@theia/scm/lib/node/scm-backend-module'));
await load(require('@theia/search-in-workspace/lib/node/search-in-workspace-backend-module'));
await load(require('@theia/plugin-ext/lib/plugin-ext-backend-module'));
await load(require('@theia/plugin-ext-vscode/lib/node/plugin-vscode-backend-module'));
await load(require('@theia/vsx-registry/lib/common/vsx-registry-common-module'));
await load(require('@theia/vsx-registry/lib/node/vsx-registry-backend-module'));
startupLog('modules loaded');
return await start(port, host, argv);
} catch (error) {
if (typeof error !== 'number') {
console.error('Failed to start the backend application:');
console.error(error);
process.exitCode = 1;
}
throw error;
}
}
@@ -0,0 +1,16 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="apple-mobile-web-app-capable" content="yes">
<title>Git.Zone IDE</title>
</head>
<body>
<div class="theia-preload"></div>
<script type="text/javascript" src="./bundle.js" charset="utf-8"></script>
</body>
</html>
@@ -0,0 +1,145 @@
// @ts-check
require('reflect-metadata');
const startupLog = (milestone) => console.debug(`Frontend: ${milestone} [${(performance.now() / 1000).toFixed(3)} s since frontend page start]`);
startupLog('loading modules...');
const { Container } = require('@theia/core/shared/inversify');
const { FrontendApplicationConfigProvider } = require('@theia/core/lib/browser/frontend-application-config-provider');
FrontendApplicationConfigProvider.set({
"applicationName": "Git.Zone IDE",
"defaultTheme": {
"light": "light",
"dark": "dark"
},
"defaultIconTheme": "theia-file-icons",
"electron": {
"windowOptions": {},
"showWindowEarly": true,
"splashScreenOptions": {},
"uriScheme": "theia"
},
"defaultLocale": "",
"validatePreferencesSchema": true,
"reloadOnReconnect": false,
"uriScheme": "theia",
"preferencesDirName": ".git-zone-ide"
});
self.MonacoEnvironment = {
getWorkerUrl: function (moduleId, label) {
return './editor.worker.js';
}
}
function load(container, jsModule) {
return Promise.resolve(jsModule)
.then(containerModule => container.load(containerModule.default));
}
async function preload(container) {
try {
await load(container, import('@theia/core/lib/browser/preload/preload-module'));
const { Preloader } = require('@theia/core/lib/browser/preload/preloader');
const preloader = container.get(Preloader);
await preloader.initialize();
} catch (reason) {
console.error('Failed to run preload scripts.');
if (reason) {
console.error(reason);
}
}
}
module.exports = (async () => {
const { messagingFrontendModule } = require('@theia/core/lib/browser/messaging/messaging-frontend-module');
const container = new Container();
container.load(messagingFrontendModule);
startupLog('container created');
await preload(container);
startupLog('preloaded');
const { MonacoInit } = require('@theia/monaco/lib/browser/monaco-init');
;
const { FrontendApplication } = require('@theia/core/lib/browser');
const { frontendApplicationModule } = require('@theia/core/lib/browser/frontend-application-module');
const { loggerFrontendModule } = require('@theia/core/lib/browser/logger-frontend-module');
container.load(frontendApplicationModule);
undefined
container.load(loggerFrontendModule);
startupLog('core modules loaded');
try {
await load(container, import('@theia/core/lib/browser/i18n/i18n-frontend-module'));
await load(container, import('@theia/core/lib/browser/menu/browser-menu-module'));
await load(container, import('@theia/core/lib/browser/window/browser-window-module'));
await load(container, import('@theia/core/lib/browser/keyboard/browser-keyboard-module'));
await load(container, import('@theia/core/lib/browser/request/browser-request-module'));
await load(container, import('@git.zone/ide-extension-opencode/lib/browser/gitzone-opencode-frontend-module'));
await load(container, import('@git.zone/ide-extension-product/lib/browser/gitzone-product-frontend-module'));
await load(container, import('@git.zone/ide-extension-remote/lib/browser/gitzone-remote-frontend-module'));
await load(container, import('@theia/variable-resolver/lib/browser/variable-resolver-frontend-module'));
await load(container, import('@theia/editor/lib/browser/editor-frontend-module'));
await load(container, import('@theia/filesystem/lib/browser/filesystem-frontend-module'));
await load(container, import('@theia/filesystem/lib/browser/download/file-download-frontend-module'));
await load(container, import('@theia/filesystem/lib/browser/file-dialog/file-dialog-module'));
await load(container, import('@theia/workspace/lib/browser/workspace-frontend-module'));
await load(container, import('@theia/markers/lib/browser/problem/problem-frontend-module'));
await load(container, import('@theia/messages/lib/browser/messages-frontend-module'));
await load(container, import('@theia/outline-view/lib/browser/outline-view-frontend-module'));
await load(container, import('@theia/monaco/lib/browser/monaco-frontend-module'));
await load(container, import('@theia/navigator/lib/browser/navigator-frontend-module'));
await load(container, import('@theia/output/lib/browser/output-frontend-module'));
await load(container, import('@theia/ai-core/lib/browser/ai-core-frontend-module'));
await load(container, import('@theia/ai-mcp/lib/browser/mcp-frontend-module'));
await load(container, import('@theia/bulk-edit/lib/browser/bulk-edit-frontend-module'));
await load(container, import('@theia/callhierarchy/lib/browser/callhierarchy-frontend-module'));
await load(container, import('@theia/console/lib/browser/console-frontend-module'));
await load(container, import('@theia/process/lib/common/process-common-module'));
await load(container, import('@theia/file-search/lib/browser/file-search-frontend-module'));
await load(container, import('@theia/terminal/lib/browser/terminal-frontend-module'));
await load(container, import('@theia/userstorage/lib/browser/user-storage-frontend-module'));
await load(container, import('@theia/preferences/lib/browser/preference-frontend-module'));
await load(container, import('@theia/terminal-manager/lib/browser/terminal-manager-frontend-module'));
await load(container, import('@theia/task/lib/browser/task-frontend-module'));
await load(container, import('@theia/test/lib/browser/view/test-view-frontend-module'));
await load(container, import('@theia/debug/lib/browser/debug-frontend-module'));
await load(container, import('@theia/editor-preview/lib/browser/editor-preview-frontend-module'));
await load(container, import('@theia/notebook/lib/browser/notebook-frontend-module'));
await load(container, import('@theia/scm/lib/browser/scm-frontend-module'));
await load(container, import('@theia/search-in-workspace/lib/browser/search-in-workspace-frontend-module'));
await load(container, import('@theia/timeline/lib/browser/timeline-frontend-module'));
await load(container, import('@theia/typehierarchy/lib/browser/typehierarchy-frontend-module'));
await load(container, import('@theia/plugin-ext/lib/plugin-ext-frontend-module'));
await load(container, import('@theia/plugin-ext-vscode/lib/browser/plugin-vscode-frontend-module'));
await load(container, import('@theia/vsx-registry/lib/common/vsx-registry-common-module'));
await load(container, import('@theia/vsx-registry/lib/browser/vsx-registry-frontend-module'));
MonacoInit.init(container);
;
startupLog('modules loaded');
await start();
} catch (reason) {
console.error('Failed to start the frontend application.');
if (reason) {
console.error(reason);
}
}
function start() {
(window['theia'] = window['theia'] || {}).container = container;
startupLog('resolving application');
const application = container.get(FrontendApplication);
startupLog('application resolved');
return application.start();
}
})();
@@ -0,0 +1,14 @@
// @ts-check
require('reflect-metadata');
const { Container } = require('@theia/core/shared/inversify');
module.exports = Promise.resolve().then(() => {
const { frontendApplicationModule } = require('@theia/core/lib/browser/frontend-application-module');
const container = new Container();
container.load(frontendApplicationModule);
container.load(require('@theia/editor/lib/browser/editor-frontend-module').default);
container.load(require('@theia/filesystem/lib/browser/filesystem-frontend-module').default);
container.load(require('@theia/monaco/lib/browser/monaco-frontend-module').default);
container.load(require('@theia/terminal/lib/browser/terminal-frontend-module').default);
container.load(require('@theia/debug/lib/browser/debug-frontend-module').default);
});
@@ -0,0 +1,33 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Theia — Secondary Window</title>
<style>
html, body {
overflow: hidden;
-ms-overflow-style: none;
}
body {
margin: 0;
}
html,
head,
body,
.secondary-widget-root,
#widget-host {
width: 100% !important;
height: 100% !important;
}
</style>
<link rel="stylesheet" href="./secondary-window.css">
</head>
<body>
<div id="widget-host"></div>
</body>
</html>
@@ -0,0 +1,21 @@
/**
* This file can be edited to customize webpack configuration.
* To reset delete this file and rerun theia build again.
*/
// @ts-check
const configs = require('./gen-webpack.config.js');
const nodeConfig = require('./gen-webpack.node.config.js');
/**
* Expose bundled modules on window.theia.moduleName namespace, e.g.
* window['theia']['@theia/core/lib/common/uri'].
* Such syntax can be used by external code, for instance, for testing.
configs[0].module.rules.push({
test: /\.js$/,
loader: require.resolve('@theia/application-manager/lib/expose-loader')
}); */
module.exports = [
...configs,
nodeConfig.config
];