From c503d5e78bb6c9cc36407a266a8fb00177134174 Mon Sep 17 00:00:00 2001 From: ewuerger Date: Tue, 7 Oct 2025 11:03:12 +0200 Subject: [PATCH 1/5] chore: Remove unused config files --- src/capellambse_context_diagrams/interop/deno.json | 5 ----- src/capellambse_context_diagrams/interop/deno.json.license | 2 -- 2 files changed, 7 deletions(-) delete mode 100644 src/capellambse_context_diagrams/interop/deno.json delete mode 100644 src/capellambse_context_diagrams/interop/deno.json.license diff --git a/src/capellambse_context_diagrams/interop/deno.json b/src/capellambse_context_diagrams/interop/deno.json deleted file mode 100644 index f7049331..00000000 --- a/src/capellambse_context_diagrams/interop/deno.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "tasks": { - "build": "deno compile --allow-read --allow-net --allow-env --no-check elk.ts" - } -} diff --git a/src/capellambse_context_diagrams/interop/deno.json.license b/src/capellambse_context_diagrams/interop/deno.json.license deleted file mode 100644 index 7581ff5e..00000000 --- a/src/capellambse_context_diagrams/interop/deno.json.license +++ /dev/null @@ -1,2 +0,0 @@ -SPDX-FileCopyrightText: 2025 Copyright DB InfraGO AG and the capellambse-context-diagrams contributors -SPDX-License-Identifier: Apache-2.0 From bff422ca2a2a57c092171c69920cec32021a0f13 Mon Sep 17 00:00:00 2001 From: ewuerger Date: Tue, 7 Oct 2025 11:06:14 +0200 Subject: [PATCH 2/5] fix: Upgrade sprotty to `1.4.0` and implement `FakeWorker` There is a bug in `elk-worker.js` such that no `FakeWorker` is exported. This commit fixes the issue with its own class definition. --- .../interop/elk.ts | 73 ++++++++++++++++++- .../interop/elkgraph-to-sprotty.ts | 2 +- 2 files changed, 70 insertions(+), 5 deletions(-) diff --git a/src/capellambse_context_diagrams/interop/elk.ts b/src/capellambse_context_diagrams/interop/elk.ts index caa4861f..65aae834 100644 --- a/src/capellambse_context_diagrams/interop/elk.ts +++ b/src/capellambse_context_diagrams/interop/elk.ts @@ -1,13 +1,78 @@ -// SPDX-FileCopyrightText: 2024 Copyright DB InfraGO AG and the capellambse-context-diagrams contributors +// SPDX-FileCopyrightText: Copyright DB InfraGO AG and the capellambse-context-diagrams contributors // SPDX-License-Identifier: Apache-2.0 import { createInterface } from "node:readline"; import process from "node:process"; -import ELK from "npm:elkjs@0.11.0"; +import ELK from "npm:elkjs@^0.11.0"; import { ElkGraphJsonToSprotty } from "./elkgraph-to-sprotty.ts"; +await import("npm:elkjs@^0.11.0/lib/elk-worker.min.js"); // initialize the ELK layout engine -// @ts-ignore Deno doesn't find this type for some reason -const elk = new ELK(); +interface MessageEvent { + data: { + id?: string; + cmd?: string; + [key: string]: any; + }; +} + +/** + * FakeWorker implementation for ELK.js in Deno environment. + * Bridges ELK's worker-based architecture with synchronous execution. + */ +class FakeWorker { + onmessage: ((event: MessageEvent) => void) | null = null; + private messageHandler: (event: MessageEvent) => void; + + constructor() { + this.messageHandler = (event: MessageEvent) => { + const data = event.data; + + try { + const globalSelf = globalThis as any; + + if (globalSelf.onmessage) { + const originalPostMessage = globalSelf.postMessage; + + globalSelf.postMessage = (msg: any) => { + if (this.onmessage) { + this.onmessage({ data: msg }); + } + }; + + globalSelf.onmessage(event); + globalSelf.postMessage = originalPostMessage; + } else { + throw new Error( + "ELK worker not initialized: globalThis.onmessage is undefined" + ); + } + } catch (err) { + if (this.onmessage) { + this.onmessage({ + data: { + id: data.id, + error: err instanceof Error ? err.message : String(err), + }, + }); + } + } + }; + } + + postMessage(msg: any): void { + setTimeout(() => { + this.messageHandler({ data: msg }); + }, 0); + } + + terminate(): void { + this.onmessage = null; + } +} + +const elk = new ELK({ + workerFactory: () => new FakeWorker(), +}); console.log("--- ELK layouter started ---"); diff --git a/src/capellambse_context_diagrams/interop/elkgraph-to-sprotty.ts b/src/capellambse_context_diagrams/interop/elkgraph-to-sprotty.ts index cafcd000..cbb9c376 100644 --- a/src/capellambse_context_diagrams/interop/elkgraph-to-sprotty.ts +++ b/src/capellambse_context_diagrams/interop/elkgraph-to-sprotty.ts @@ -15,7 +15,7 @@ import type { SGraphSchema, Point, Dimension, -} from "npm:sprotty@^0.8.0"; +} from "npm:sprotty@^1.4.0"; import { ElkShape, ElkNode, From 53c5d8af16ffd45c6c18a505752be169c7f6661c Mon Sep 17 00:00:00 2001 From: ewuerger Date: Tue, 7 Oct 2025 11:47:24 +0200 Subject: [PATCH 3/5] ci: Upgrade deno to `2.5.x` --- .github/workflows/build-test-publish.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-test-publish.yml b/.github/workflows/build-test-publish.yml index dcff8584..edb158db 100644 --- a/.github/workflows/build-test-publish.yml +++ b/.github/workflows/build-test-publish.yml @@ -43,7 +43,7 @@ jobs: - name: Setup Deno uses: denoland/setup-deno@v2 with: - deno-version: "2.3.6" + deno-version: "2.5.x" - name: Run unit tests run: uv run pytest -n auto From f16b5bb6abb4ec16a3c60f18e6571b3caf33f461 Mon Sep 17 00:00:00 2001 From: ewuerger Date: Mon, 3 Nov 2025 16:08:58 +0100 Subject: [PATCH 4/5] refactor: Implement Deno config file for elkjs This enables dependabot to update JS dependencies. --- .github/dependabot.yml | 11 ++++++ src/capellambse_context_diagrams/_elkjs.py | 6 ++- .../interop/deno.json | 6 +++ .../interop/deno.json.license | 2 + .../interop/elk.ts | 37 ++++++++----------- .../interop/elkgraph-to-sprotty.ts | 2 +- .../interop/package.json | 10 +++++ .../interop/package.json.license | 2 + 8 files changed, 52 insertions(+), 24 deletions(-) create mode 100644 src/capellambse_context_diagrams/interop/deno.json create mode 100644 src/capellambse_context_diagrams/interop/deno.json.license create mode 100644 src/capellambse_context_diagrams/interop/package.json create mode 100644 src/capellambse_context_diagrams/interop/package.json.license diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 05fdb23f..cf2d9d70 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -13,3 +13,14 @@ updates: patterns: ["*"] commit-message: prefix: chore + + - package-ecosystem: npm + directory: /src/capellambse_context_diagrams/interop + schedule: + interval: weekly + day: wednesday + groups: + js-dependencies: + patterns: ["*"] + commit-message: + prefix: chore diff --git a/src/capellambse_context_diagrams/_elkjs.py b/src/capellambse_context_diagrams/_elkjs.py index aa1fc511..9cfb5311 100644 --- a/src/capellambse_context_diagrams/_elkjs.py +++ b/src/capellambse_context_diagrams/_elkjs.py @@ -400,14 +400,18 @@ def _spawn_process_binary(self) -> None: def _spawn_process_deno(self) -> None: log.debug("Spawning elk.js helper process using deno") deno_location = shutil.which("deno") - script_location = pathlib.Path(__file__).parent / "interop" / "elk.ts" if deno_location is None: raise RuntimeError("Deno is not installed") + interop_dir = pathlib.Path(__file__).parent / "interop" + script_location = interop_dir / "elk.ts" + config_location = interop_dir / "deno.json" + self._proc = subprocess.Popen( [ deno_location, "run", + f"--config={config_location}", "--allow-read", "--allow-net", "--allow-env", diff --git a/src/capellambse_context_diagrams/interop/deno.json b/src/capellambse_context_diagrams/interop/deno.json new file mode 100644 index 00000000..61f6c967 --- /dev/null +++ b/src/capellambse_context_diagrams/interop/deno.json @@ -0,0 +1,6 @@ +{ + "imports": { + "elkjs": "npm:elkjs@^0.11.0", + "sprotty": "npm:sprotty@^1.4.0" + } +} diff --git a/src/capellambse_context_diagrams/interop/deno.json.license b/src/capellambse_context_diagrams/interop/deno.json.license new file mode 100644 index 00000000..12276205 --- /dev/null +++ b/src/capellambse_context_diagrams/interop/deno.json.license @@ -0,0 +1,2 @@ +SPDX-FileCopyrightText: Copyright DB InfraGO AG and the capellambse-context-diagrams contributors +SPDX-License-Identifier: Apache-2.0 diff --git a/src/capellambse_context_diagrams/interop/elk.ts b/src/capellambse_context_diagrams/interop/elk.ts index 65aae834..26b2cc4d 100644 --- a/src/capellambse_context_diagrams/interop/elk.ts +++ b/src/capellambse_context_diagrams/interop/elk.ts @@ -3,16 +3,18 @@ import { createInterface } from "node:readline"; import process from "node:process"; -import ELK from "npm:elkjs@^0.11.0"; +import ELK from "npm:elkjs"; import { ElkGraphJsonToSprotty } from "./elkgraph-to-sprotty.ts"; -await import("npm:elkjs@^0.11.0/lib/elk-worker.min.js"); // initialize the ELK layout engine +await import("npm:elkjs/lib/elk-worker.min.js"); // initialize the ELK layout engine + +interface Message { + id?: string; + cmd?: string; + [key: string]: any; +} interface MessageEvent { - data: { - id?: string; - cmd?: string; - [key: string]: any; - }; + data: Message; } /** @@ -21,25 +23,22 @@ interface MessageEvent { */ class FakeWorker { onmessage: ((event: MessageEvent) => void) | null = null; - private messageHandler: (event: MessageEvent) => void; - - constructor() { - this.messageHandler = (event: MessageEvent) => { - const data = event.data; + postMessage(msg: Message): void { + setTimeout(() => { try { const globalSelf = globalThis as any; if (globalSelf.onmessage) { const originalPostMessage = globalSelf.postMessage; - globalSelf.postMessage = (msg: any) => { + globalSelf.postMessage = (responseMsg: Message) => { if (this.onmessage) { - this.onmessage({ data: msg }); + this.onmessage({ data: responseMsg }); } }; - globalSelf.onmessage(event); + globalSelf.onmessage({ data: msg }); globalSelf.postMessage = originalPostMessage; } else { throw new Error( @@ -50,18 +49,12 @@ class FakeWorker { if (this.onmessage) { this.onmessage({ data: { - id: data.id, + id: msg.id, error: err instanceof Error ? err.message : String(err), }, }); } } - }; - } - - postMessage(msg: any): void { - setTimeout(() => { - this.messageHandler({ data: msg }); }, 0); } diff --git a/src/capellambse_context_diagrams/interop/elkgraph-to-sprotty.ts b/src/capellambse_context_diagrams/interop/elkgraph-to-sprotty.ts index cbb9c376..4bc8d7c5 100644 --- a/src/capellambse_context_diagrams/interop/elkgraph-to-sprotty.ts +++ b/src/capellambse_context_diagrams/interop/elkgraph-to-sprotty.ts @@ -15,7 +15,7 @@ import type { SGraphSchema, Point, Dimension, -} from "npm:sprotty@^1.4.0"; +} from "npm:sprotty"; import { ElkShape, ElkNode, diff --git a/src/capellambse_context_diagrams/interop/package.json b/src/capellambse_context_diagrams/interop/package.json new file mode 100644 index 00000000..6e23228b --- /dev/null +++ b/src/capellambse_context_diagrams/interop/package.json @@ -0,0 +1,10 @@ +{ + "name": "capellambse-context-diagrams-interop", + "version": "0.0.0", + "private": true, + "description": "Dependencies for Deno interop layer", + "dependencies": { + "elkjs": "^0.11.0", + "sprotty": "^1.4.0" + } +} diff --git a/src/capellambse_context_diagrams/interop/package.json.license b/src/capellambse_context_diagrams/interop/package.json.license new file mode 100644 index 00000000..12276205 --- /dev/null +++ b/src/capellambse_context_diagrams/interop/package.json.license @@ -0,0 +1,2 @@ +SPDX-FileCopyrightText: Copyright DB InfraGO AG and the capellambse-context-diagrams contributors +SPDX-License-Identifier: Apache-2.0 From 4504a6eae1ca019976d7d21cc8986960156e2346 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ernst=20W=C3=BCrger?= Date: Tue, 4 Nov 2025 14:11:29 +0100 Subject: [PATCH 5/5] revert: Don't version js libs with dependabot --- .github/dependabot.yml | 11 ----------- src/capellambse_context_diagrams/interop/package.json | 10 ---------- .../interop/package.json.license | 2 -- 3 files changed, 23 deletions(-) delete mode 100644 src/capellambse_context_diagrams/interop/package.json delete mode 100644 src/capellambse_context_diagrams/interop/package.json.license diff --git a/.github/dependabot.yml b/.github/dependabot.yml index cf2d9d70..05fdb23f 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -13,14 +13,3 @@ updates: patterns: ["*"] commit-message: prefix: chore - - - package-ecosystem: npm - directory: /src/capellambse_context_diagrams/interop - schedule: - interval: weekly - day: wednesday - groups: - js-dependencies: - patterns: ["*"] - commit-message: - prefix: chore diff --git a/src/capellambse_context_diagrams/interop/package.json b/src/capellambse_context_diagrams/interop/package.json deleted file mode 100644 index 6e23228b..00000000 --- a/src/capellambse_context_diagrams/interop/package.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "name": "capellambse-context-diagrams-interop", - "version": "0.0.0", - "private": true, - "description": "Dependencies for Deno interop layer", - "dependencies": { - "elkjs": "^0.11.0", - "sprotty": "^1.4.0" - } -} diff --git a/src/capellambse_context_diagrams/interop/package.json.license b/src/capellambse_context_diagrams/interop/package.json.license deleted file mode 100644 index 12276205..00000000 --- a/src/capellambse_context_diagrams/interop/package.json.license +++ /dev/null @@ -1,2 +0,0 @@ -SPDX-FileCopyrightText: Copyright DB InfraGO AG and the capellambse-context-diagrams contributors -SPDX-License-Identifier: Apache-2.0