Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 0 additions & 6 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,6 @@
"${workspaceRoot}/examples/workflow-server/*/lib/**/*.js",
"${workspaceRoot}/packages/**/*/lib/**/*.js"
],
"sourceMapPathOverrides": {
"webpack://@eclipse-glsp-examples/workflow-server/(.+)": "${workspaceFolder}/examples/workflow-server/$1"
},
"smartStep": true,
"internalConsoleOptions": "openOnSessionStart",
"outputCapture": "std"
Expand All @@ -100,9 +97,6 @@
"${workspaceRoot}/examples/workflow-server/*/lib/**/*.js",
"${workspaceRoot}/packages/**/*/lib/**/*.js"
],
"sourceMapPathOverrides": {
"webpack://@eclipse-glsp-examples/workflow-server/(.+)": "${workspaceFolder}/examples/workflow-server/$1"
},
"smartStep": true,
"internalConsoleOptions": "openOnSessionStart",
"outputCapture": "std"
Expand Down
11 changes: 11 additions & 0 deletions .vscode/tasks.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,17 @@
},
"problemMatcher": ["$tsc-watch"]
},
{
"label": "Start Example GLSP server (dev, hot reload)",
"type": "shell",
"group": "none",
"command": "yarn dev",
"presentation": {
"reveal": "always",
"panel": "dedicated"
},
"problemMatcher": []
},
{
"label": "Execute all glsp-server tests",
"type": "shell",
Expand Down
6 changes: 4 additions & 2 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,10 @@ Eclipse GLSP Server Node monorepo. Provides the TypeScript-based server framewor
- **Build**: `yarn` from root installs and compiles everything
- **Compile**: `yarn compile` (runs `tsc -b` with project references)
- **Clean**: `yarn clean`
- **Watch**: `yarn watch` (parallel TypeScript + bundle watch)
- **Start example server**: `yarn start` (TCP on 5007) or `yarn start:websocket` (WebSocket on 8081)
- **Watch**: `yarn watch` (parallel TypeScript + esbuild bundle watch)
- **Bundle**: `yarn bundle` (esbuild bundles the workflow example, node + webworker targets)
- **Start example server**: `yarn start` (TCP on 5007) or `yarn start:websocket` (WebSocket on 8081) — runs the pre-built bundle
- **Dev server (hot reload)**: `yarn dev` (TCP on 5007) or `yarn dev:ws` (WebSocket on 8081) — esbuild watches `src` and restarts the server on change

## Validation

Expand Down
2 changes: 1 addition & 1 deletion examples/workflow-server-mcp-demo/.gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
# Populated by `yarn start` (verbatim assets + synced worker bundle + webpack output)
# Populated by `yarn start` (verbatim assets + synced worker bundle + esbuild output)
dist/
75 changes: 75 additions & 0 deletions examples/workflow-server-mcp-demo/esbuild.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/********************************************************************************
* Copyright (c) 2026 EclipseSource and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the Eclipse
* Public License v. 2.0 are satisfied: GNU General Public License, version 2
* with the GNU Classpath Exception which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
********************************************************************************/
// @ts-check
const { resolve } = require('node:path');
const esbuild = require('esbuild');

const watch = process.argv.slice(2).includes('--watch');

/**
* Reports the build progress and surfaces errors/warnings in a format that
* VS Code's `$esbuild-watch` problem matcher can pick up.
* @type {import('esbuild').Plugin}
*/
const esbuildProblemMatcherPlugin = {
name: 'esbuild-problem-matcher',
setup(build) {
build.onStart(() => {
console.log(`${watch ? '[watch] ' : ''}build started`);
});
build.onEnd(result => {
result.errors.forEach(({ text, location }) => {
console.error(`✘ [ERROR] ${text}`);
if (location) {
console.error(` ${location.file}:${location.line}:${location.column}:`);
}
});
console.log(`${watch ? '[watch] ' : ''}build finished`);
});
}
};

// Bundle `vscode-jsonrpc/browser` plus the page-side script into a single file emitted into
// `dist/`, alongside the verbatim assets copied from `public/` and the worker bundle synced
// from `@eclipse-glsp-examples/workflow-server-bundled-web` by `scripts/prepare-dist.mjs`.
/** @type {import('esbuild').BuildOptions} */
const config = {
entryPoints: [resolve(__dirname, 'src/index.js')],
outfile: resolve(__dirname, 'dist/index.bundle.js'),
bundle: true,
sourcemap: true,
platform: 'browser',
format: 'iife',
target: 'es2019',
mainFields: ['browser', 'module', 'main'],
conditions: ['browser'],
logLevel: 'silent',
plugins: [esbuildProblemMatcherPlugin]
};

async function main() {
if (watch) {
const ctx = await esbuild.context(config);
await ctx.watch();
} else {
await esbuild.build(config);
}
}

main().catch(e => {
console.error(e);
process.exit(1);
});
7 changes: 3 additions & 4 deletions examples/workflow-server-mcp-demo/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"name": "Eclipse GLSP"
},
"scripts": {
"build": "webpack",
"build": "node esbuild.js",
"clean": "rimraf dist",
"prestart": "node ./scripts/prepare-dist.mjs && yarn build",
"start": "npx -y serve -l 8000 ./dist"
Expand All @@ -23,8 +23,7 @@
"@eclipse-glsp-examples/workflow-server-bundled-web": "2.8.0-next"
},
"devDependencies": {
"vscode-jsonrpc": "8.2.0",
"webpack": "^5.75.0",
"webpack-cli": "^5.0.1"
"esbuild": "~0.28.0",
"vscode-jsonrpc": "8.2.0"
}
}
4 changes: 2 additions & 2 deletions examples/workflow-server-mcp-demo/scripts/prepare-dist.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
********************************************************************************/

// Populates `dist/` with everything `serve` needs that webpack doesn't emit:
// Populates `dist/` with everything `serve` needs that esbuild doesn't emit:
// - verbatim files from `public/` (index.html, mcp-service-worker.js)
// - the worker bundle from `@eclipse-glsp-examples/workflow-server-bundled-web`
// Webpack writes `index.bundle.js` into the same dir as a separate step.
// esbuild writes `index.bundle.js` into the same dir as a separate step.

import { copyFileSync, existsSync, mkdirSync, readdirSync, statSync } from 'node:fs';
import { createRequire } from 'node:module';
Expand Down
33 changes: 0 additions & 33 deletions examples/workflow-server-mcp-demo/webpack.config.js

This file was deleted.

140 changes: 140 additions & 0 deletions examples/workflow-server/esbuild.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
/********************************************************************************
* Copyright (c) 2022-2026 EclipseSource and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the Eclipse
* Public License v. 2.0 are satisfied: GNU General Public License, version 2
* with the GNU Classpath Exception which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
********************************************************************************/
// @ts-check
const { spawn } = require('node:child_process');
const { resolve } = require('node:path');
const esbuild = require('esbuild');

const argv = process.argv.slice(2);
const watch = argv.includes('--watch');
// Dev mode: build only the node target and (re)start the server after each successful build.
const runNode = argv.includes('--run-node');
// Everything after `--` is forwarded verbatim to the spawned node server (e.g. `--port 5007`).
const dashDash = argv.indexOf('--');
const serverArgs = dashDash >= 0 ? argv.slice(dashDash + 1) : [];

const bundledDir = resolve(__dirname, '..', 'workflow-server-bundled');
const bundledWebDir = resolve(__dirname, '..', 'workflow-server-bundled-web');

/**
* Reports the build progress and surfaces errors/warnings in a format that
* VS Code's `$esbuild-watch` problem matcher can pick up.
* @type {import('esbuild').Plugin}
*/
const esbuildProblemMatcherPlugin = {
name: 'esbuild-problem-matcher',
setup(build) {
build.onStart(() => {
console.log(`${watch ? '[watch] ' : ''}build started`);
});
build.onEnd(result => {
result.errors.forEach(({ text, location }) => {
console.error(`✘ [ERROR] ${text}`);
if (location) {
console.error(` ${location.file}:${location.line}:${location.column}:`);
}
});
console.log(`${watch ? '[watch] ' : ''}build finished`);
});
}
};

/** @type {import('esbuild').BuildOptions} */
const common = {
bundle: true,
// Minify one-shot production builds; keep watch/dev output readable and fast to rebuild.
// `sourcemap` still maps the (minified) output back to the original TypeScript sources.
minify: !watch,
// Preserve original class/function names through minification — GLSP's logger and error
// messages use `constructor.name` for labels, which would otherwise be mangled.
keepNames: true,
sourcemap: true,
logLevel: 'silent',
tsconfig: resolve(__dirname, 'tsconfig.json'),
plugins: [esbuildProblemMatcherPlugin]
};

/** @type {import('esbuild').BuildOptions} */
const nodeConfig = {
...common,
entryPoints: [resolve(__dirname, 'src/node/app.ts')],
outfile: resolve(bundledDir, 'wf-glsp-server-node.js'),
platform: 'node',
format: 'cjs',
target: 'node22',
// `ws` requires these optional native deps in a try/catch; keep them external so the
// graceful-fallback path works and esbuild does not error on the missing modules.
external: ['bufferutil', 'utf-8-validate']
};

/** @type {import('esbuild').BuildOptions} */
const webworkerConfig = {
...common,
entryPoints: [resolve(__dirname, 'src/browser/app.ts')],
outfile: resolve(bundledWebDir, 'wf-glsp-server-webworker.js'),
platform: 'browser',
format: 'iife',
target: 'es2019',
// Honor the legacy `browser` package field + browser condition for transitive deps.
mainFields: ['browser', 'module', 'main'],
conditions: ['browser']
};

/** Restart the bundled node server after every successful build. */
function runNodePlugin() {
/** @type {import('node:child_process').ChildProcess | undefined} */
let child;
const stop = () => child?.kill('SIGTERM');
process.on('SIGINT', () => {
stop();
process.exit(0);
});
return {
name: 'run-node-server',
setup(build) {
build.onEnd(result => {
if (result.errors.length > 0) {
// Keep the last good server running so a broken build does not crash the loop.
return;
}
stop();
child = spawn('node', ['--enable-source-maps', nodeConfig.outfile, ...serverArgs], { stdio: 'inherit' });
});
}
};
}

async function run(config) {
if (watch) {
const ctx = await esbuild.context(config);
await ctx.watch();
} else {
await esbuild.build(config);
}
}

async function main() {
if (runNode) {
await run({ ...nodeConfig, plugins: [esbuildProblemMatcherPlugin, runNodePlugin()] });
} else {
await Promise.all([run(nodeConfig), run(webworkerConfig)]);
}
}

main().catch(e => {
console.error(e);
process.exit(1);
});
13 changes: 6 additions & 7 deletions examples/workflow-server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,14 +46,15 @@
"browser.js"
],
"scripts": {
"build": "tsc -b && yarn bundle && yarn bundle:browser",
"bundle": "webpack",
"bundle:browser": "webpack --env target=webworker ",
"build": "tsc -b && yarn bundle",
"bundle": "node esbuild.js",
"clean": "rimraf lib *.tsbuildinfo",
"dev": "node esbuild.js --watch --run-node -- --port 5007",
"dev:ws": "node esbuild.js --watch --run-node -- -w --port 8081",
"generate:index": "glsp generateIndex src/browser src/common src/node -s -f",
"lint": "eslint ./src",
"watch": "tsc -w",
"watch:bundle": "webpack -w"
"watch:bundle": "node esbuild.js --watch"
},
"dependencies": {
"@eclipse-glsp/layout-elk": "2.8.0-next",
Expand All @@ -62,9 +63,7 @@
"inversify": "^6.1.3"
},
"devDependencies": {
"source-map-loader": "^4.0.1",
"webpack": "^5.75.0",
"webpack-cli": "^5.0.1"
"esbuild": "~0.28.0"
},
"publishConfig": {
"access": "public"
Expand Down
Loading