@hydranium/glsp-client-theia 1.0.0-next.10

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 (94) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +134 -0
  3. package/lib/browser/action-dispatcher.d.ts +85 -0
  4. package/lib/browser/action-dispatcher.d.ts.map +1 -0
  5. package/lib/browser/action-dispatcher.js +238 -0
  6. package/lib/browser/action-dispatcher.js.map +1 -0
  7. package/lib/browser/client-contribution.d.ts +53 -0
  8. package/lib/browser/client-contribution.d.ts.map +1 -0
  9. package/lib/browser/client-contribution.js +111 -0
  10. package/lib/browser/client-contribution.js.map +1 -0
  11. package/lib/browser/diagram-loader.d.ts +123 -0
  12. package/lib/browser/diagram-loader.d.ts.map +1 -0
  13. package/lib/browser/diagram-loader.js +153 -0
  14. package/lib/browser/diagram-loader.js.map +1 -0
  15. package/lib/browser/diagram-only-marker-manager.d.ts +28 -0
  16. package/lib/browser/diagram-only-marker-manager.d.ts.map +1 -0
  17. package/lib/browser/diagram-only-marker-manager.js +44 -0
  18. package/lib/browser/diagram-only-marker-manager.js.map +1 -0
  19. package/lib/browser/diagram-widget.d.ts +97 -0
  20. package/lib/browser/diagram-widget.d.ts.map +1 -0
  21. package/lib/browser/diagram-widget.js +172 -0
  22. package/lib/browser/diagram-widget.js.map +1 -0
  23. package/lib/browser/glsp-client-theia-module.d.ts +40 -0
  24. package/lib/browser/glsp-client-theia-module.d.ts.map +1 -0
  25. package/lib/browser/glsp-client-theia-module.js +46 -0
  26. package/lib/browser/glsp-client-theia-module.js.map +1 -0
  27. package/lib/browser/glsp-diagram-manager.d.ts +46 -0
  28. package/lib/browser/glsp-diagram-manager.d.ts.map +1 -0
  29. package/lib/browser/glsp-diagram-manager.js +66 -0
  30. package/lib/browser/glsp-diagram-manager.js.map +1 -0
  31. package/lib/browser/glsp-message-service.d.ts +59 -0
  32. package/lib/browser/glsp-message-service.d.ts.map +1 -0
  33. package/lib/browser/glsp-message-service.js +97 -0
  34. package/lib/browser/glsp-message-service.js.map +1 -0
  35. package/lib/browser/glsp-theia-frontend-module.d.ts +110 -0
  36. package/lib/browser/glsp-theia-frontend-module.d.ts.map +1 -0
  37. package/lib/browser/glsp-theia-frontend-module.js +133 -0
  38. package/lib/browser/glsp-theia-frontend-module.js.map +1 -0
  39. package/lib/browser/hidden-bounds-updater.d.ts +122 -0
  40. package/lib/browser/hidden-bounds-updater.d.ts.map +1 -0
  41. package/lib/browser/hidden-bounds-updater.js +207 -0
  42. package/lib/browser/hidden-bounds-updater.js.map +1 -0
  43. package/lib/browser/hydranium-glsp-diagram-configuration.d.ts +52 -0
  44. package/lib/browser/hydranium-glsp-diagram-configuration.d.ts.map +1 -0
  45. package/lib/browser/hydranium-glsp-diagram-configuration.js +72 -0
  46. package/lib/browser/hydranium-glsp-diagram-configuration.js.map +1 -0
  47. package/lib/browser/index.d.ts +20 -0
  48. package/lib/browser/index.d.ts.map +1 -0
  49. package/lib/browser/index.js +38 -0
  50. package/lib/browser/index.js.map +1 -0
  51. package/lib/index.d.ts +10 -0
  52. package/lib/index.d.ts.map +1 -0
  53. package/lib/index.js +39 -0
  54. package/lib/index.js.map +1 -0
  55. package/lib/node/connection-container-module.d.ts +22 -0
  56. package/lib/node/connection-container-module.d.ts.map +1 -0
  57. package/lib/node/connection-container-module.js +36 -0
  58. package/lib/node/connection-container-module.js.map +1 -0
  59. package/lib/node/glsp-server-connection-handler.d.ts +49 -0
  60. package/lib/node/glsp-server-connection-handler.d.ts.map +1 -0
  61. package/lib/node/glsp-server-connection-handler.js +64 -0
  62. package/lib/node/glsp-server-connection-handler.js.map +1 -0
  63. package/lib/node/index.d.ts +11 -0
  64. package/lib/node/index.d.ts.map +1 -0
  65. package/lib/node/index.js +28 -0
  66. package/lib/node/index.js.map +1 -0
  67. package/lib/testing/bind-recorder.d.ts +67 -0
  68. package/lib/testing/bind-recorder.d.ts.map +1 -0
  69. package/lib/testing/bind-recorder.js +72 -0
  70. package/lib/testing/bind-recorder.js.map +1 -0
  71. package/lib/testing/index.d.ts +10 -0
  72. package/lib/testing/index.d.ts.map +1 -0
  73. package/lib/testing/index.js +30 -0
  74. package/lib/testing/index.js.map +1 -0
  75. package/package.json +114 -0
  76. package/src/browser/action-dispatcher.ts +257 -0
  77. package/src/browser/client-contribution.ts +100 -0
  78. package/src/browser/diagram-loader.ts +173 -0
  79. package/src/browser/diagram-only-marker-manager.ts +33 -0
  80. package/src/browser/diagram-widget.ts +178 -0
  81. package/src/browser/glsp-client-theia-module.ts +54 -0
  82. package/src/browser/glsp-diagram-manager.ts +67 -0
  83. package/src/browser/glsp-message-service.ts +90 -0
  84. package/src/browser/glsp-theia-frontend-module.ts +157 -0
  85. package/src/browser/hidden-bounds-updater.ts +212 -0
  86. package/src/browser/hydranium-glsp-diagram-configuration.ts +63 -0
  87. package/src/browser/index.ts +22 -0
  88. package/src/index.ts +23 -0
  89. package/src/node/connection-container-module.ts +34 -0
  90. package/src/node/glsp-server-connection-handler.ts +69 -0
  91. package/src/node/index.ts +12 -0
  92. package/src/testing/bind-recorder.ts +126 -0
  93. package/src/testing/index.ts +15 -0
  94. package/style/diagram-loading.css +67 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 CrossBreeze, EclipseSource and others.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,134 @@
1
+ # `@hydranium/glsp-client-theia`
2
+
3
+ Theia client primitives for the hydranium **GLSP head** — the companion of
4
+ `@hydranium/glsp-server` in the
5
+ [Hydranium](https://github.com/eclipse-emfcloud/hydranium) framework.
6
+
7
+ It sits between `@eclipse-glsp/theia-integration` and an adopter's diagram: the
8
+ module composition, the instrumented dispatcher and bounds updater, the loading
9
+ overlay, the marker-propagation switch, and the backend socket bridge. Install it
10
+ if you are mounting a hydranium GLSP diagram in a Theia application.
11
+
12
+ ## What it gives you
13
+
14
+ - **`AbstractHydraniumGlspTheiaFrontendModule`** — a `GLSPTheiaFrontendModule`
15
+ subclass that absorbs the overrides every adopter otherwise writes verbatim.
16
+ You declare `diagramLanguage`, `diagramConfiguration` and `diagramManager`;
17
+ optionally set `logLevelPreference` (the base then binds the log-threshold
18
+ contribution for you) and override `bindClientContribution()` — returning
19
+ `SkipClientContribution` for a secondary diagram type that shares a server with
20
+ a primary one.
21
+ - **`createGlspClientTheiaModule(context, options)`** — the standard per-diagram
22
+ bindings, all unconditional: the cross-head `ChannelLogger`,
23
+ `HydraniumGlspActionDispatcher`, `HydraniumDiagramLoader`,
24
+ `HydraniumHiddenBoundsUpdater`, and `HydraniumGlspMessageService`. Each
25
+ replaces a GLSP default with a strict superset of its behaviour, so a head that
26
+ wants the original rebinds that one token back.
27
+ - **Loading feedback that cannot silently vanish.** `HydraniumDiagramLoader`
28
+ catches every load failure — the dispatcher-init, connect and first
29
+ `RequestModelAction` steps upstream leaves unwrapped — routes it to the Output
30
+ channel, and reports it as an error `StatusAction`. It publishes a terminal
31
+ `DiagramLoadOutcome`, which `HydraniumGlspDiagramWidget` keys its opaque canvas
32
+ overlay on (`DIAGRAM_LOADING_CLASS`, `DIAGRAM_LOADING_FAILED_CLASS`).
33
+ `HydraniumGlspMessageService` then drops the now-redundant "Model loading in
34
+ progress" toast (`MODEL_LOADING_PROGRESS_TITLE`) and forwards every other
35
+ progress report untouched.
36
+ - **Instrumentation.** `HydraniumGlspActionDispatcher` logs action traffic into
37
+ the shared Output channel and pairs requests with responses — by id, or by kind
38
+ for the GLSP flow actions that carry none (`HYDRANIUM_DEFAULT_LOGGED_KINDS`,
39
+ `HYDRANIUM_DEFAULT_KIND_PAIRS`, extensible via
40
+ `HydraniumGlspActionDispatcherOptions`). `HydraniumHiddenBoundsUpdater` emits
41
+ one trace line per bounds request with the measured element count and the raw
42
+ `getBBox` cost — the client-side phase that scales with rendered elements
43
+ rather than model size.
44
+ - **`AbstractHydraniumGlspDiagramConfiguration`** with
45
+ `propagateMarkersToProblemsView` — set it `false` for a head whose co-resident
46
+ LSP already publishes the same diagnostics, and the per-diagram container binds
47
+ `NoOpExternalMarkerManager` instead: markers still decorate the diagram, but
48
+ Theia's Problems view stops double-listing them.
49
+ **`AbstractHydraniumGlspDiagramManager`** derives the language-correlated
50
+ getters from one descriptor plus a label.
51
+ - **`HydraniumGlspClientContribution`** — for a server that starts late: it tails
52
+ the Output channel for a server-printed ready marker and defers `start` until a
53
+ workspace is open.
54
+ - **Backend (`./node`)** — `GlspServerConnectionHandler` (the socket bridge,
55
+ plugging in `@eclipse-glsp/theia-integration`'s `SocketConnectionForwarder`) and
56
+ `createGlspConnectionContainerModule(handler)` for the frontend-scoped module
57
+ boilerplate.
58
+
59
+ ## Install
60
+
61
+ ```bash
62
+ npm install @hydranium/glsp-client-theia
63
+ ```
64
+
65
+ You must already have a Theia application wired for GLSP — `@eclipse-glsp/client`
66
+ and `@eclipse-glsp/theia-integration` are peers, not bundled — and a running
67
+ hydranium GLSP server. The declared peer dependencies are:
68
+
69
+ | Peer | Range |
70
+ | --------------------------------- | ------------- |
71
+ | `@eclipse-glsp/client` | `^2.6.0` |
72
+ | `@eclipse-glsp/theia-integration` | `^2.6.0` |
73
+ | `@hydranium/client-theia` | `^1.0.0-next` |
74
+ | `@hydranium/protocol` | `^1.0.0-next` |
75
+ | `@theia/core` | `^1.71.0` |
76
+ | `@theia/output` | `^1.71.0` |
77
+ | `@theia/process` | `^1.71.0` |
78
+ | `@theia/workspace` | `^1.71.0` |
79
+ | `inversify` | `^6.0.0` |
80
+ | `snabbdom` | `^3.5.1` |
81
+
82
+ ## Wiring
83
+
84
+ This package declares no `theiaExtensions` — it is a library your own Theia
85
+ extension builds on. That extension declares the entries; a diagram is one
86
+ frontend/backend pair:
87
+
88
+ - the **frontend** entry points at a module that
89
+ `export default new MyDiagramModule()`, where `MyDiagramModule` extends
90
+ `AbstractHydraniumGlspTheiaFrontendModule`. Your `DiagramConfiguration`
91
+ subclass calls `createGlspClientTheiaModule` in its container initialisation,
92
+ passing the `channelLogger` name;
93
+ - the **backend** entry is typically
94
+ `export default createGlspConnectionContainerModule(MyHandler)`, where
95
+ `MyHandler` extends `GlspServerConnectionHandler`. The handler's
96
+ `languageContributionId` decides the per-language service path Theia routes
97
+ frontend connections to.
98
+
99
+ **The `style/` directory needs no action from you.** It holds one stylesheet,
100
+ `diagram-loading.css`, for the widget's loading overlay, and the widget module
101
+ imports it itself — precisely so an adopter cannot ship an unstyled `div` in
102
+ normal flow by forgetting it. It is listed in `files` because it must be present
103
+ in the published tarball for that import to resolve; your bundler needs a CSS
104
+ loader, which a Theia application's webpack configuration already has. Colours
105
+ come from `--theia-*` theme variables, and every rule is overridable from a
106
+ stylesheet loaded afterwards.
107
+
108
+ ## Entry points
109
+
110
+ | Subpath | Holds | Environment |
111
+ | ----------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------- |
112
+ | `.` | Re-exports `./browser` — the larger of the two tiers and safe to load anywhere. | browser-neutral (gated) |
113
+ | `./browser` | The frontend module bases, `createGlspClientTheiaModule`, the dispatcher, loader, widget, bounds updater, message service, diagram manager and configuration bases, `NoOpExternalMarkerManager` | browser / Theia frontend (gated) |
114
+ | `./node` | `GlspServerConnectionHandler`, `createGlspConnectionContainerModule` | Node / Theia backend |
115
+ | `./testing` | `makeBindRecorder`, the GLSP-module-specific Inversify double (the cross-head doubles live in `@hydranium/client-theia/testing`) | browser-neutral (gated) |
116
+
117
+ Every subpath also has a `./lib/<name>` twin for consumers on
118
+ `moduleResolution: "Node"`. "Gated" means the repository's neutral-bundle check
119
+ enforces that the entry bundles for the browser with no `node:*` import,
120
+ transitive ones included; `./node` is deliberately outside that gate. Also
121
+ worth reading: [what "gated neutral" does and does not promise](../../docs/concepts/browser-hosting.md#a-note-on-what-gated-neutral-does-and-does-not-promise).
122
+
123
+ ## Status
124
+
125
+ Alpha — pre-v0, not yet published. The API is not stable and may change without a
126
+ deprecation cycle. See [`docs/concepts/architecture.md`](../../docs/concepts/architecture.md) for
127
+ the GLSP head's place among the heads, and the
128
+ [repository README](../../README.md) for current status and known limitations.
129
+
130
+ ## License
131
+
132
+ `MIT` — see this package's [`LICENSE`](./LICENSE). Third-party notices for the
133
+ runtime dependency closure are collected in the repository
134
+ [`NOTICE.md`](../../NOTICE.md).
@@ -0,0 +1,85 @@
1
+ /********************************************************************************
2
+ * Copyright (c) 2026 CrossBreeze, EclipseSource and others.
3
+ *
4
+ * This program and the accompanying materials are made available under the
5
+ * terms of the MIT License which is available in the project root.
6
+ *
7
+ * SPDX-License-Identifier: MIT
8
+ ********************************************************************************/
9
+ import { type Action, GLSPActionDispatcher } from '@eclipse-glsp/client';
10
+ import { ChannelLogger } from '@hydranium/client-theia/lib/browser';
11
+ import { type Tracer } from '@hydranium/protocol';
12
+ /** Default subset of action kinds the framework dispatcher will log: the GLSP
13
+ * traffic an observer reading the Output channel typically wants to see. All
14
+ * are standard `@eclipse-glsp/client` kinds; adopters with custom action kinds
15
+ * extend via `extraLoggedKinds`. */
16
+ export declare const HYDRANIUM_DEFAULT_LOGGED_KINDS: ReadonlySet<string>;
17
+ /** Default request → response kind pairs for GLSP 'flow' actions that do NOT
18
+ * carry a requestId/responseId — so the dispatcher matches by kind (FIFO).
19
+ * Id-based matching still wins when a requestId is present. */
20
+ export declare const HYDRANIUM_DEFAULT_KIND_PAIRS: ReadonlyMap<string, string>;
21
+ /** Additive options. Adopters with custom action kinds pass extras here; the
22
+ * framework defaults always apply (you cannot un-log a kind the framework
23
+ * considers worth logging — subclass + override `dispatch` if you must). */
24
+ export interface HydraniumGlspActionDispatcherOptions {
25
+ readonly extraLoggedKinds?: Iterable<string>;
26
+ readonly extraKindPairs?: Iterable<readonly [string, string]>;
27
+ /** Replaces the default `summarize` body entirely. Use for adopter-domain
28
+ * action kinds where the framework default returns ''. */
29
+ readonly summarize?: (action: Action) => string;
30
+ }
31
+ /**
32
+ * Wraps every dispatch so action traffic appears in the framework Output
33
+ * channel, interleaved with server log lines. Instrumenting the dispatcher
34
+ * (rather than per-kind handlers) catches ResponseActions that bypass the
35
+ * handler pipeline.
36
+ *
37
+ * The framework defaults cover the standard GLSP kinds worth logging, not every
38
+ * kind the protocol defines. Adopters with custom kinds either pass
39
+ * `extraLoggedKinds` / `extraKindPairs` to the constructor (via a
40
+ * `toDynamicValue` binding) or subclass and override.
41
+ */
42
+ export declare class HydraniumGlspActionDispatcher extends GLSPActionDispatcher {
43
+ protected readonly channel: ChannelLogger;
44
+ protected readonly tracer: Tracer;
45
+ protected readonly loggedKinds: ReadonlySet<string>;
46
+ protected readonly kindPairs: ReadonlyMap<string, string>;
47
+ protected readonly kindPairsReverse: ReadonlyMap<string, string>;
48
+ protected pairCounter: number;
49
+ /** Pending requests keyed by requestId (for actions that carry one). */
50
+ protected pendingById: Map<string, {
51
+ id: number;
52
+ start: number;
53
+ }>;
54
+ /** FIFO queue per response kind, used for `flow` pairs without requestId/responseId. */
55
+ protected pendingByKind: Map<string, {
56
+ id: number;
57
+ start: number;
58
+ }[]>;
59
+ constructor(options?: HydraniumGlspActionDispatcherOptions);
60
+ initialize(): Promise<void>;
61
+ /**
62
+ * Register the one-shot 'model initialized' timing line. Instrumentation
63
+ * only — guarded so a tracer failure degrades logging rather than aborting
64
+ * diagram init. `initialize()` runs inside `DiagramLoader.load()`, whose
65
+ * caller (`GLSPDiagramWidget.onAfterAttach`) neither awaits nor catches the
66
+ * returned promise; an error thrown here would therefore escape as an
67
+ * uncaught rejection that blanks the diagram with no server-side signal.
68
+ */
69
+ protected registerInitTiming(): void;
70
+ dispatch(action: Action): Promise<void>;
71
+ protected logAction(action: Action): void;
72
+ protected classify(action: Action): {
73
+ verb: string;
74
+ direction: string;
75
+ };
76
+ /** Emit `[request #N]` on the request side, `[response #N, Xms]` on the matching response side.
77
+ * Match first by requestId/responseId, then by known kind pairs (FIFO). */
78
+ protected trackPair(action: Action): string;
79
+ protected formatResponse(entry: {
80
+ id: number;
81
+ start: number;
82
+ }): string;
83
+ protected summarize(action: Action): string;
84
+ }
85
+ //# sourceMappingURL=action-dispatcher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"action-dispatcher.d.ts","sourceRoot":"","sources":["../../src/browser/action-dispatcher.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAElF,OAAO,EACJ,KAAK,MAAM,EAEX,oBAAoB,EAmBtB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,aAAa,EAAiB,MAAM,qCAAqC,CAAC;AACnF,OAAO,EAAE,KAAK,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAGlD;;;qCAGqC;AACrC,eAAO,MAAM,8BAA8B,EAAE,WAAW,CAAC,MAAM,CAe7D,CAAC;AAEH;;gEAEgE;AAChE,eAAO,MAAM,4BAA4B,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAInE,CAAC;AAEH;;6EAE6E;AAC7E,MAAM,WAAW,oCAAoC;IAClD,QAAQ,CAAC,gBAAgB,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC7C,QAAQ,CAAC,cAAc,CAAC,EAAE,QAAQ,CAAC,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAC9D;+DAC2D;IAC3D,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,MAAM,CAAC;CAClD;AAED;;;;;;;;;;GAUG;AACH,qBACa,6BAA8B,SAAQ,oBAAoB;IAC7C,SAAS,CAAC,QAAQ,CAAC,OAAO,EAAG,aAAa,CAAC;IAC3C,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAG,MAAM,CAAC;IAE1D,SAAS,CAAC,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IACpD,SAAS,CAAC,QAAQ,CAAC,SAAS,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC1D,SAAS,CAAC,QAAQ,CAAC,gBAAgB,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAEjE,SAAS,CAAC,WAAW,SAAK;IAC1B,wEAAwE;IACxE,SAAS,CAAC,WAAW;YAAyB,MAAM;eAAS,MAAM;OAAM;IACzE,wFAAwF;IACxF,SAAS,CAAC,aAAa;YAA+B,MAAM;eAAS,MAAM;SAAO;gBAEzD,OAAO,CAAC,EAAE,oCAAoC;IAa9D,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IASpC;;;;;;;OAOG;IACH,SAAS,CAAC,kBAAkB,IAAI,IAAI;IAQ3B,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAOhD,SAAS,CAAC,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAczC,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE;IAkBvE;gFAC4E;IAC5E,SAAS,CAAC,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM;IAiC3C,SAAS,CAAC,cAAc,CAAC,KAAK,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,MAAM;IAKtE,SAAS,CAAC,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM;CAoC7C"}
@@ -0,0 +1,238 @@
1
+ "use strict";
2
+ /********************************************************************************
3
+ * Copyright (c) 2026 CrossBreeze, EclipseSource and others.
4
+ *
5
+ * This program and the accompanying materials are made available under the
6
+ * terms of the MIT License which is available in the project root.
7
+ *
8
+ * SPDX-License-Identifier: MIT
9
+ ********************************************************************************/
10
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
11
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
12
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
13
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
14
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
15
+ };
16
+ var __metadata = (this && this.__metadata) || function (k, v) {
17
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
18
+ };
19
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
20
+ return function (target, key) { decorator(target, key, paramIndex); }
21
+ };
22
+ Object.defineProperty(exports, "__esModule", { value: true });
23
+ exports.HydraniumGlspActionDispatcher = exports.HYDRANIUM_DEFAULT_KIND_PAIRS = exports.HYDRANIUM_DEFAULT_LOGGED_KINDS = void 0;
24
+ const client_1 = require("@eclipse-glsp/client");
25
+ const browser_1 = require("@hydranium/client-theia/lib/browser");
26
+ const inversify_1 = require("@theia/core/shared/inversify");
27
+ /** Default subset of action kinds the framework dispatcher will log: the GLSP
28
+ * traffic an observer reading the Output channel typically wants to see. All
29
+ * are standard `@eclipse-glsp/client` kinds; adopters with custom action kinds
30
+ * extend via `extraLoggedKinds`. */
31
+ exports.HYDRANIUM_DEFAULT_LOGGED_KINDS = new Set([
32
+ client_1.SetModelAction.KIND,
33
+ client_1.UpdateModelAction.KIND,
34
+ client_1.RequestBoundsAction.KIND,
35
+ client_1.ComputedBoundsAction.KIND,
36
+ client_1.SetDirtyStateAction.KIND,
37
+ client_1.SetEditModeAction.KIND,
38
+ client_1.SetMarkersAction.KIND,
39
+ client_1.SetTypeHintsAction.KIND,
40
+ client_1.StatusAction.KIND,
41
+ client_1.MessageAction.KIND,
42
+ client_1.RejectAction.KIND,
43
+ client_1.RequestContextActions.KIND,
44
+ client_1.RequestModelAction.KIND,
45
+ client_1.RequestTypeHintsAction.KIND
46
+ ]);
47
+ /** Default request → response kind pairs for GLSP 'flow' actions that do NOT
48
+ * carry a requestId/responseId — so the dispatcher matches by kind (FIFO).
49
+ * Id-based matching still wins when a requestId is present. */
50
+ exports.HYDRANIUM_DEFAULT_KIND_PAIRS = new Map([
51
+ [client_1.RequestModelAction.KIND, client_1.SetModelAction.KIND],
52
+ [client_1.RequestTypeHintsAction.KIND, client_1.SetTypeHintsAction.KIND],
53
+ [client_1.RequestBoundsAction.KIND, client_1.ComputedBoundsAction.KIND]
54
+ ]);
55
+ /**
56
+ * Wraps every dispatch so action traffic appears in the framework Output
57
+ * channel, interleaved with server log lines. Instrumenting the dispatcher
58
+ * (rather than per-kind handlers) catches ResponseActions that bypass the
59
+ * handler pipeline.
60
+ *
61
+ * The framework defaults cover the standard GLSP kinds worth logging, not every
62
+ * kind the protocol defines. Adopters with custom kinds either pass
63
+ * `extraLoggedKinds` / `extraKindPairs` to the constructor (via a
64
+ * `toDynamicValue` binding) or subclass and override.
65
+ */
66
+ let HydraniumGlspActionDispatcher = class HydraniumGlspActionDispatcher extends client_1.GLSPActionDispatcher {
67
+ channel;
68
+ tracer;
69
+ loggedKinds;
70
+ kindPairs;
71
+ kindPairsReverse;
72
+ pairCounter = 0;
73
+ /** Pending requests keyed by requestId (for actions that carry one). */
74
+ pendingById = new Map();
75
+ /** FIFO queue per response kind, used for `flow` pairs without requestId/responseId. */
76
+ pendingByKind = new Map();
77
+ constructor(options) {
78
+ super();
79
+ const extraLogged = options?.extraLoggedKinds ? Array.from(options.extraLoggedKinds) : [];
80
+ this.loggedKinds = new Set([...exports.HYDRANIUM_DEFAULT_LOGGED_KINDS, ...extraLogged]);
81
+ const extraPairs = options?.extraKindPairs ? Array.from(options.extraKindPairs) : [];
82
+ const pairs = new Map([...exports.HYDRANIUM_DEFAULT_KIND_PAIRS, ...extraPairs]);
83
+ this.kindPairs = pairs;
84
+ this.kindPairsReverse = new Map(Array.from(pairs, ([req, res]) => [res, req]));
85
+ if (options?.summarize) {
86
+ this.summarize = options.summarize;
87
+ }
88
+ }
89
+ initialize() {
90
+ // `initialize()` is called many times; super is idempotent, but our callback registration
91
+ // isn't. Register the timing log only on the first call (when super.initialized is unset).
92
+ if (!this.initialized) {
93
+ this.registerInitTiming();
94
+ }
95
+ return super.initialize();
96
+ }
97
+ /**
98
+ * Register the one-shot 'model initialized' timing line. Instrumentation
99
+ * only — guarded so a tracer failure degrades logging rather than aborting
100
+ * diagram init. `initialize()` runs inside `DiagramLoader.load()`, whose
101
+ * caller (`GLSPDiagramWidget.onAfterAttach`) neither awaits nor catches the
102
+ * returned promise; an error thrown here would therefore escape as an
103
+ * uncaught rejection that blanks the diagram with no server-side signal.
104
+ */
105
+ registerInitTiming() {
106
+ try {
107
+ this.tracer.time('Model initialized', () => this.onceModelInitialized(), 'info', { logAfterMs: 0 });
108
+ }
109
+ catch (err) {
110
+ this.channel.error('Failed to register model-initialized timing instrumentation', err);
111
+ }
112
+ }
113
+ dispatch(action) {
114
+ if (this.loggedKinds.has(action.kind)) {
115
+ this.logAction(action);
116
+ }
117
+ return super.dispatch(action);
118
+ }
119
+ logAction(action) {
120
+ const { verb, direction } = this.classify(action);
121
+ const summary = this.summarize(action);
122
+ const timing = this.trackPair(action);
123
+ const parts = [`${verb} action '${action.kind}'`, `[${direction}]`];
124
+ if (summary) {
125
+ parts.push(`[${summary}]`);
126
+ }
127
+ if (timing) {
128
+ parts.push(timing);
129
+ }
130
+ this.channel.trace(parts.join(' '));
131
+ }
132
+ classify(action) {
133
+ // GLSP marks client-produced computedBounds as ServerAction to suppress forwarding; stays local.
134
+ if (client_1.LocalComputedBoundsAction.is(action)) {
135
+ return { verb: 'Process', direction: 'client → client' };
136
+ }
137
+ // Marked by GLSPModelSource.messageReceived — arrived from the server.
138
+ if (client_1.ServerAction.is(action)) {
139
+ return { verb: 'Receive', direction: 'server → client' };
140
+ }
141
+ // GLSPModelSource is registered as handler for every server-handled kind (configureServeActions),
142
+ // so its presence means the action will be forwarded to the server.
143
+ const handlers = this.actionHandlerRegistry.get(action.kind);
144
+ if (handlers.some(handler => handler instanceof client_1.GLSPModelSource)) {
145
+ return { verb: 'Send', direction: 'client → server' };
146
+ }
147
+ return { verb: 'Process', direction: 'client → client' };
148
+ }
149
+ /** Emit `[request #N]` on the request side, `[response #N, Xms]` on the matching response side.
150
+ * Match first by requestId/responseId, then by known kind pairs (FIFO). */
151
+ trackPair(action) {
152
+ // Response side.
153
+ if (client_1.ResponseAction.hasValidResponseId(action)) {
154
+ const entry = this.pendingById.get(action.responseId);
155
+ if (entry) {
156
+ this.pendingById.delete(action.responseId);
157
+ return this.formatResponse(entry);
158
+ }
159
+ }
160
+ if (this.kindPairsReverse.has(action.kind)) {
161
+ const queue = this.pendingByKind.get(action.kind);
162
+ const entry = queue?.shift();
163
+ if (entry) {
164
+ return this.formatResponse(entry);
165
+ }
166
+ }
167
+ // Request side.
168
+ if (client_1.RequestAction.is(action) && action.requestId) {
169
+ const entry = { id: ++this.pairCounter, start: performance.now() };
170
+ this.pendingById.set(action.requestId, entry);
171
+ return `[request #${entry.id}]`;
172
+ }
173
+ if (this.kindPairs.has(action.kind)) {
174
+ const responseKind = this.kindPairs.get(action.kind);
175
+ const entry = { id: ++this.pairCounter, start: performance.now() };
176
+ const queue = this.pendingByKind.get(responseKind) ?? [];
177
+ queue.push(entry);
178
+ this.pendingByKind.set(responseKind, queue);
179
+ return `[request #${entry.id}]`;
180
+ }
181
+ return '';
182
+ }
183
+ formatResponse(entry) {
184
+ const elapsed = Math.round(performance.now() - entry.start);
185
+ return `[response #${entry.id}, ${elapsed}ms]`;
186
+ }
187
+ summarize(action) {
188
+ if (client_1.SetModelAction.is(action) || client_1.UpdateModelAction.is(action)) {
189
+ const root = action.newRoot;
190
+ return `rootType=${root?.type ?? 'none'} children=${root?.children?.length ?? 0}`;
191
+ }
192
+ if (client_1.RequestBoundsAction.is(action)) {
193
+ return `rootType=${action.newRoot.type} children=${action.newRoot.children?.length ?? 0}`;
194
+ }
195
+ if (client_1.ComputedBoundsAction.is(action)) {
196
+ return `bounds=${action.bounds.length}`;
197
+ }
198
+ if (client_1.SetDirtyStateAction.is(action)) {
199
+ return `isDirty=${action.isDirty} reason=${action.reason ?? 'n/a'}`;
200
+ }
201
+ if (client_1.SetEditModeAction.is(action)) {
202
+ return `editMode=${action.editMode}`;
203
+ }
204
+ if (client_1.SetMarkersAction.is(action)) {
205
+ return `markers=${action.markers.length}`;
206
+ }
207
+ if (client_1.StatusAction.is(action) || client_1.MessageAction.is(action)) {
208
+ // severity=NONE with empty message is the conventional 'clear' signal.
209
+ const clear = action.severity === 'NONE' && !action.message ? ' (clear)' : '';
210
+ return `severity=${action.severity} message="${action.message.slice(0, 160)}"${clear}`;
211
+ }
212
+ if (client_1.RejectAction.is(action)) {
213
+ return `reason="${action.message.slice(0, 160)}"`;
214
+ }
215
+ if (client_1.SetTypeHintsAction.is(action)) {
216
+ return `shapes=${action.shapeHints.length} edges=${action.edgeHints.length}`;
217
+ }
218
+ if (client_1.RequestContextActions.is(action)) {
219
+ return `contextId=${action.contextId}`;
220
+ }
221
+ return '';
222
+ }
223
+ };
224
+ exports.HydraniumGlspActionDispatcher = HydraniumGlspActionDispatcher;
225
+ __decorate([
226
+ (0, inversify_1.inject)(browser_1.ChannelLogger),
227
+ __metadata("design:type", browser_1.ChannelLogger)
228
+ ], HydraniumGlspActionDispatcher.prototype, "channel", void 0);
229
+ __decorate([
230
+ (0, inversify_1.inject)(browser_1.ChannelTracer),
231
+ __metadata("design:type", Object)
232
+ ], HydraniumGlspActionDispatcher.prototype, "tracer", void 0);
233
+ exports.HydraniumGlspActionDispatcher = HydraniumGlspActionDispatcher = __decorate([
234
+ (0, inversify_1.injectable)(),
235
+ __param(0, (0, inversify_1.unmanaged)()),
236
+ __metadata("design:paramtypes", [Object])
237
+ ], HydraniumGlspActionDispatcher);
238
+ //# sourceMappingURL=action-dispatcher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"action-dispatcher.js","sourceRoot":"","sources":["../../src/browser/action-dispatcher.ts"],"names":[],"mappings":";AAAA;;;;;;;kFAOkF;;;;;;;;;;;;;;;AAElF,iDAsB8B;AAC9B,iEAAmF;AAEnF,4DAA6E;AAE7E;;;qCAGqC;AACxB,QAAA,8BAA8B,GAAwB,IAAI,GAAG,CAAS;IAChF,uBAAc,CAAC,IAAI;IACnB,0BAAiB,CAAC,IAAI;IACtB,4BAAmB,CAAC,IAAI;IACxB,6BAAoB,CAAC,IAAI;IACzB,4BAAmB,CAAC,IAAI;IACxB,0BAAiB,CAAC,IAAI;IACtB,yBAAgB,CAAC,IAAI;IACrB,2BAAkB,CAAC,IAAI;IACvB,qBAAY,CAAC,IAAI;IACjB,sBAAa,CAAC,IAAI;IAClB,qBAAY,CAAC,IAAI;IACjB,8BAAqB,CAAC,IAAI;IAC1B,2BAAkB,CAAC,IAAI;IACvB,+BAAsB,CAAC,IAAI;CAC7B,CAAC,CAAC;AAEH;;gEAEgE;AACnD,QAAA,4BAA4B,GAAgC,IAAI,GAAG,CAAiB;IAC9F,CAAC,2BAAkB,CAAC,IAAI,EAAE,uBAAc,CAAC,IAAI,CAAC;IAC9C,CAAC,+BAAsB,CAAC,IAAI,EAAE,2BAAkB,CAAC,IAAI,CAAC;IACtD,CAAC,4BAAmB,CAAC,IAAI,EAAE,6BAAoB,CAAC,IAAI,CAAC;CACvD,CAAC,CAAC;AAaH;;;;;;;;;;GAUG;AAEI,IAAM,6BAA6B,GAAnC,MAAM,6BAA8B,SAAQ,6BAAoB;IAC1B,OAAO,CAAiB;IACxB,MAAM,CAAU;IAEvC,WAAW,CAAsB;IACjC,SAAS,CAA8B;IACvC,gBAAgB,CAA8B;IAEvD,WAAW,GAAG,CAAC,CAAC;IAC1B,wEAAwE;IAC9D,WAAW,GAAG,IAAI,GAAG,EAAyC,CAAC;IACzE,wFAAwF;IAC9E,aAAa,GAAG,IAAI,GAAG,EAAgD,CAAC;IAElF,YAAyB,OAA8C;QACpE,KAAK,EAAE,CAAC;QACR,MAAM,WAAW,GAAG,OAAO,EAAE,gBAAgB,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAC1F,IAAI,CAAC,WAAW,GAAG,IAAI,GAAG,CAAS,CAAC,GAAG,sCAA8B,EAAE,GAAG,WAAW,CAAC,CAAC,CAAC;QACxF,MAAM,UAAU,GAAG,OAAO,EAAE,cAAc,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACrF,MAAM,KAAK,GAAG,IAAI,GAAG,CAAiB,CAAC,GAAG,oCAA4B,EAAE,GAAG,UAAU,CAAC,CAAC,CAAC;QACxF,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;QACvB,IAAI,CAAC,gBAAgB,GAAG,IAAI,GAAG,CAAiB,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC;QAC/F,IAAI,OAAO,EAAE,SAAS,EAAE,CAAC;YACtB,IAAI,CAAC,SAAS,GAAG,OAAO,CAAC,SAAS,CAAC;QACtC,CAAC;IACJ,CAAC;IAEQ,UAAU;QAChB,0FAA0F;QAC1F,2FAA2F;QAC3F,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;YACrB,IAAI,CAAC,kBAAkB,EAAE,CAAC;QAC7B,CAAC;QACD,OAAO,KAAK,CAAC,UAAU,EAAE,CAAC;IAC7B,CAAC;IAED;;;;;;;OAOG;IACO,kBAAkB;QACzB,IAAI,CAAC;YACF,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,mBAAmB,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,oBAAoB,EAAE,EAAE,MAAM,EAAE,EAAE,UAAU,EAAE,CAAC,EAAE,CAAC,CAAC;QACvG,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACZ,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,6DAA6D,EAAE,GAAG,CAAC,CAAC;QAC1F,CAAC;IACJ,CAAC;IAEQ,QAAQ,CAAC,MAAc;QAC7B,IAAI,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;YACrC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;QAC1B,CAAC;QACD,OAAO,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IACjC,CAAC;IAES,SAAS,CAAC,MAAc;QAC/B,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QAClD,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;QACvC,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;QACtC,MAAM,KAAK,GAAG,CAAC,GAAG,IAAI,YAAY,MAAM,CAAC,IAAI,GAAG,EAAE,IAAI,SAAS,GAAG,CAAC,CAAC;QACpE,IAAI,OAAO,EAAE,CAAC;YACX,KAAK,CAAC,IAAI,CAAC,IAAI,OAAO,GAAG,CAAC,CAAC;QAC9B,CAAC;QACD,IAAI,MAAM,EAAE,CAAC;YACV,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACtB,CAAC;QACD,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IACvC,CAAC;IAES,QAAQ,CAAC,MAAc;QAC9B,iGAAiG;QACjG,IAAI,kCAAyB,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC;YACxC,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,EAAE,iBAAiB,EAAE,CAAC;QAC5D,CAAC;QACD,uEAAuE;QACvE,IAAI,qBAAY,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC;YAC3B,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,EAAE,iBAAiB,EAAE,CAAC;QAC5D,CAAC;QACD,kGAAkG;QAClG,oEAAoE;QACpE,MAAM,QAAQ,GAAG,IAAI,CAAC,qBAAqB,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAC7D,IAAI,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,YAAY,wBAAe,CAAC,EAAE,CAAC;YAChE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,iBAAiB,EAAE,CAAC;QACzD,CAAC;QACD,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,EAAE,iBAAiB,EAAE,CAAC;IAC5D,CAAC;IAED;gFAC4E;IAClE,SAAS,CAAC,MAAc;QAC/B,iBAAiB;QACjB,IAAI,uBAAc,CAAC,kBAAkB,CAAC,MAAM,CAAC,EAAE,CAAC;YAC7C,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;YACtD,IAAI,KAAK,EAAE,CAAC;gBACT,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;gBAC3C,OAAO,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;YACrC,CAAC;QACJ,CAAC;QACD,IAAI,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;YAC1C,MAAM,KAAK,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YAClD,MAAM,KAAK,GAAG,KAAK,EAAE,KAAK,EAAE,CAAC;YAC7B,IAAI,KAAK,EAAE,CAAC;gBACT,OAAO,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;YACrC,CAAC;QACJ,CAAC;QACD,gBAAgB;QAChB,IAAI,sBAAa,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI,MAAM,CAAC,SAAS,EAAE,CAAC;YAChD,MAAM,KAAK,GAAG,EAAE,EAAE,EAAE,EAAE,IAAI,CAAC,WAAW,EAAE,KAAK,EAAE,WAAW,CAAC,GAAG,EAAE,EAAE,CAAC;YACnE,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,MAAM,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;YAC9C,OAAO,aAAa,KAAK,CAAC,EAAE,GAAG,CAAC;QACnC,CAAC;QACD,IAAI,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;YACnC,MAAM,YAAY,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAE,CAAC;YACtD,MAAM,KAAK,GAAG,EAAE,EAAE,EAAE,EAAE,IAAI,CAAC,WAAW,EAAE,KAAK,EAAE,WAAW,CAAC,GAAG,EAAE,EAAE,CAAC;YACnE,MAAM,KAAK,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,YAAY,CAAC,IAAI,EAAE,CAAC;YACzD,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAClB,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,YAAY,EAAE,KAAK,CAAC,CAAC;YAC5C,OAAO,aAAa,KAAK,CAAC,EAAE,GAAG,CAAC;QACnC,CAAC;QACD,OAAO,EAAE,CAAC;IACb,CAAC;IAES,cAAc,CAAC,KAAoC;QAC1D,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC;QAC5D,OAAO,cAAc,KAAK,CAAC,EAAE,KAAK,OAAO,KAAK,CAAC;IAClD,CAAC;IAES,SAAS,CAAC,MAAc;QAC/B,IAAI,uBAAc,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI,0BAAiB,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC;YAC7D,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,CAAC;YAC5B,OAAO,YAAY,IAAI,EAAE,IAAI,IAAI,MAAM,aAAa,IAAI,EAAE,QAAQ,EAAE,MAAM,IAAI,CAAC,EAAE,CAAC;QACrF,CAAC;QACD,IAAI,4BAAmB,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC;YAClC,OAAO,YAAY,MAAM,CAAC,OAAO,CAAC,IAAI,aAAa,MAAM,CAAC,OAAO,CAAC,QAAQ,EAAE,MAAM,IAAI,CAAC,EAAE,CAAC;QAC7F,CAAC;QACD,IAAI,6BAAoB,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC;YACnC,OAAO,UAAU,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;QAC3C,CAAC;QACD,IAAI,4BAAmB,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC;YAClC,OAAO,WAAW,MAAM,CAAC,OAAO,WAAW,MAAM,CAAC,MAAM,IAAI,KAAK,EAAE,CAAC;QACvE,CAAC;QACD,IAAI,0BAAiB,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC;YAChC,OAAO,YAAY,MAAM,CAAC,QAAQ,EAAE,CAAC;QACxC,CAAC;QACD,IAAI,yBAAgB,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC;YAC/B,OAAO,WAAW,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;QAC7C,CAAC;QACD,IAAI,qBAAY,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI,sBAAa,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC;YACvD,uEAAuE;YACvE,MAAM,KAAK,GAAG,MAAM,CAAC,QAAQ,KAAK,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC;YAC9E,OAAO,YAAY,MAAM,CAAC,QAAQ,aAAa,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,IAAI,KAAK,EAAE,CAAC;QAC1F,CAAC;QACD,IAAI,qBAAY,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC;YAC3B,OAAO,WAAW,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,GAAG,CAAC;QACrD,CAAC;QACD,IAAI,2BAAkB,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC;YACjC,OAAO,UAAU,MAAM,CAAC,UAAU,CAAC,MAAM,UAAU,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC;QAChF,CAAC;QACD,IAAI,8BAAqB,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC;YACpC,OAAO,aAAa,MAAM,CAAC,SAAS,EAAE,CAAC;QAC1C,CAAC;QACD,OAAO,EAAE,CAAC;IACb,CAAC;CACH,CAAA;AAvKY,sEAA6B;AACG;IAAzC,IAAA,kBAAM,EAAC,uBAAa,CAAC;8BAA8B,uBAAa;8DAAC;AACxB;IAAzC,IAAA,kBAAM,EAAC,uBAAa,CAAC;;6DAAoC;wCAFhD,6BAA6B;IADzC,IAAA,sBAAU,GAAE;IAeG,WAAA,IAAA,qBAAS,GAAE,CAAA;;GAdd,6BAA6B,CAuKzC"}
@@ -0,0 +1,53 @@
1
+ /********************************************************************************
2
+ * Copyright (c) 2026 CrossBreeze, EclipseSource and others.
3
+ *
4
+ * This program and the accompanying materials are made available under the
5
+ * terms of the MIT License which is available in the project root.
6
+ *
7
+ * SPDX-License-Identifier: MIT
8
+ ********************************************************************************/
9
+ import { type GLSPClient } from '@eclipse-glsp/client';
10
+ import { BaseGLSPClientContribution } from '@eclipse-glsp/theia-integration';
11
+ import { OutputChannelManager } from '@theia/output/lib/browser/output-channel';
12
+ import { WorkspaceService } from '@theia/workspace/lib/browser';
13
+ /** Options for `HydraniumGlspClientContribution`. The channel name is the
14
+ * Theia Output channel both the LSP and GLSP sides write to (so log lines
15
+ * interleave); the ready marker is a server-printed substring that signals
16
+ * "the GLSP server is accepting client connections". */
17
+ export interface ClientContributionOptions {
18
+ readonly languageContributionId: string;
19
+ readonly channelName: string;
20
+ readonly readyMarker: string;
21
+ }
22
+ /**
23
+ * Theia GLSP client contribution for adopters whose GLSP server runs in a
24
+ * sideloaded VS Code extension process (or any other deferred-start setup).
25
+ * The behaviours adopters reliably need are lifted:
26
+ *
27
+ * 1. `waitForBackendConnected`: tail the OutputChannel for a server-printed
28
+ * ready marker. While a socket connection might open earlier, the GLSP
29
+ * server typically does internal initialisation before it can accept
30
+ * client connections — we wait for it to say so.
31
+ * 2. `start`: defer until a workspace is opened. If Theia starts without a
32
+ * workspace, this prevents the frontend-backend connection (and its
33
+ * "connecting" progress spinner) from firing prematurely.
34
+ *
35
+ * A `GLSPClient` override filtering inbound messages by clientId is
36
+ * deliberately NOT provided: upstream's `BaseJsonrpcGLSPClient.onActionMessage`
37
+ * already filters by clientId, so the `TheiaJsonrpcGLSPClient` returned by
38
+ * `BaseGLSPClientContribution.createGLSPClient` is correct as-is.
39
+ */
40
+ export declare class HydraniumGlspClientContribution extends BaseGLSPClientContribution {
41
+ protected outputChannelManager: OutputChannelManager;
42
+ protected readonly workspaceService: WorkspaceService;
43
+ readonly id: string;
44
+ protected readonly channelName: string;
45
+ protected readonly readyMarker: string;
46
+ constructor(options: ClientContributionOptions);
47
+ /** Wait for the server to print its ready marker into the OutputChannel.
48
+ * Resolves immediately if the marker is already present (server started
49
+ * before the client contribution mounted). */
50
+ protected waitForBackendConnected(): Promise<void>;
51
+ protected start(glspClient: GLSPClient): Promise<void>;
52
+ }
53
+ //# sourceMappingURL=client-contribution.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client-contribution.d.ts","sourceRoot":"","sources":["../../src/browser/client-contribution.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAElF,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,0BAA0B,EAAE,MAAM,iCAAiC,CAAC;AAG7E,OAAO,EAAE,oBAAoB,EAAE,MAAM,0CAA0C,CAAC;AAChF,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAEhE;;;yDAGyD;AACzD,MAAM,WAAW,yBAAyB;IACvC,QAAQ,CAAC,sBAAsB,EAAE,MAAM,CAAC;IACxC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC/B;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,qBACa,+BAAgC,SAAQ,0BAA0B;IAC9C,SAAS,CAAC,oBAAoB,EAAG,oBAAoB,CAAC;IAC1D,SAAS,CAAC,QAAQ,CAAC,gBAAgB,EAAG,gBAAgB,CAAC;IAEjF,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IACvC,SAAS,CAAC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;gBAEd,OAAO,EAAE,yBAAyB;IAO3D;;mDAE+C;cAC/B,uBAAuB,IAAI,OAAO,CAAC,IAAI,CAAC;cAkB/B,KAAK,CAAC,UAAU,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;CAkBvE"}