@hydranium/glsp-client-theia 1.0.0-next.123 → 1.0.0-next.127

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.
package/README.md CHANGED
@@ -51,8 +51,20 @@ if you are mounting a hydranium GLSP diagram in a Theia application.
51
51
  - **`HydraniumGlspClientContribution`** — for a server that starts late: it tails
52
52
  the Output channel for a server-printed ready marker and defers `start` until a
53
53
  workspace is open.
54
+ - **`HydraniumGlspSaveable`** — the diagram widget's saveable. Each save is a
55
+ `RequestSaveModelAction` the server answers: the save resolves on its own
56
+ response, and rejects on its own rejection or after 10 s rather than GLSP's
57
+ 2 s. It stays dirty while a save is pending, so Theia's exit check still
58
+ counts it. The server answers through
59
+ `HydraniumGlspRequestSaveModelActionHandler`, which
60
+ `AbstractHydraniumGlspDiagramModule` registers; against a server that does
61
+ not advertise the request, the saveable behaves as GLSP's does. The dirty
62
+ flag follows the server, so an edit whose dirty state has not arrived when
63
+ Save All runs is not saved. Under the `fire-and-forget` `SaveDeliveryPolicy`
64
+ the server answers before the disk write finishes, and answers a failed
65
+ write as saved.
54
66
  - **Backend (`./node`)** — `GlspServerConnectionHandler` (the socket bridge,
55
- plugging in `@eclipse-glsp/theia-integration`'s `SocketConnectionForwarder`) and
67
+ over `@hydranium/client-theia`'s `SocketChannelForwarder`) and
56
68
  `createGlspConnectionContainerModule(handler)` for the frontend-scoped module
57
69
  boilerplate.
58
70
 
@@ -107,12 +119,12 @@ stylesheet loaded afterwards.
107
119
 
108
120
  ## Entry points
109
121
 
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) |
122
+ | Subpath | Holds | Environment |
123
+ | ----------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------- |
124
+ | `.` | Re-exports `./browser` — the larger of the two tiers and safe to load anywhere. | browser-neutral (gated) |
125
+ | `./browser` | The frontend module bases, `createGlspClientTheiaModule`, the dispatcher, loader, widget and its saveable, bounds updater, message service, diagram manager and configuration bases, `NoOpExternalMarkerManager` | browser / Theia frontend (gated) |
126
+ | `./node` | `GlspServerConnectionHandler`, `createGlspConnectionContainerModule` | Node / Theia backend |
127
+ | `./testing` | `makeBindRecorder`, the GLSP-module-specific Inversify double (the cross-head doubles live in `@hydranium/client-theia/testing`) | browser-neutral (gated) |
116
128
 
117
129
  Every subpath also has a `./lib/<name>` twin for consumers on
118
130
  `moduleResolution: "Node"`. "Gated" means the repository's neutral-bundle check
@@ -6,8 +6,9 @@
6
6
  *
7
7
  * SPDX-License-Identifier: MIT
8
8
  ********************************************************************************/
9
- import { GLSPDiagramWidget } from '@eclipse-glsp/theia-integration';
9
+ import { GLSPDiagramWidget, type GLSPDiagramWidgetOptions } from '@eclipse-glsp/theia-integration';
10
10
  import { type Message } from '@theia/core/lib/browser';
11
+ import { type Container } from '@theia/core/shared/inversify';
11
12
  import { type DiagramLoadOutcome, HydraniumDiagramLoader } from './diagram-loader';
12
13
  import '../../style/diagram-loading.css';
13
14
  /** Class on the overlay root. Adopters style / override via this contract. */
@@ -45,9 +46,20 @@ export declare const DIAGRAM_LOADING_FAILED_CLASS = "hydranium-diagram-loading-f
45
46
  * Bound unconditionally by `AbstractHydraniumGlspTheiaFrontendModule`. To opt out,
46
47
  * override {@link showLoadingOverlay} to a no-op; to change what is rendered,
47
48
  * override {@link createLoadingOverlay} or {@link loadingLabel}.
49
+ *
50
+ * Its saveable is a {@link HydraniumGlspSaveable}, which keeps a pending save
51
+ * dirty, so Theia's exit check still counts it; see {@link createSaveable}.
48
52
  */
49
53
  export declare class HydraniumGlspDiagramWidget extends GLSPDiagramWidget {
50
54
  protected loadingOverlay?: HTMLElement;
55
+ /**
56
+ * Replaces the saveable GLSP's `configure` builds inline, with no factory
57
+ * seam. The widget factory calls `configure` before the widget reaches the
58
+ * shell, so Theia only ever tracks this one.
59
+ */
60
+ configure(options: GLSPDiagramWidgetOptions, diContainer: Container): void;
61
+ /** The widget's saveable. Override to change how saves and dirty state behave. */
62
+ protected createSaveable(): GLSPDiagramWidget['saveable'];
51
63
  protected onAfterAttach(msg: Message): void;
52
64
  dispose(): void;
53
65
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"diagram-widget.d.ts","sourceRoot":"","sources":["../../src/browser/diagram-widget.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAGlF,OAAO,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AAGpE,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,yBAAyB,CAAC;AAEvD,OAAO,EAAE,KAAK,kBAAkB,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AAInF,OAAO,iCAAiC,CAAC;AAEzC,8EAA8E;AAC9E,eAAO,MAAM,qBAAqB,8BAA8B,CAAC;AAEjE;kFACkF;AAClF,eAAO,MAAM,4BAA4B,qCAAoC,CAAC;AAE9E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,qBACa,0BAA2B,SAAQ,iBAAiB;IAC9D,SAAS,CAAC,cAAc,CAAC,EAAE,WAAW,CAAC;cAEpB,aAAa,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI;IAO3C,OAAO,IAAI,IAAI;IAKxB;;;;;;;OAOG;IACH,SAAS,CAAC,kBAAkB,IAAI,IAAI;IAmBpC;;;;;;OAMG;IACH,SAAS,CAAC,aAAa,CAAC,OAAO,EAAE,kBAAkB,GAAG,IAAI;IAQ1D;;;;;;;;;OASG;IACH,SAAS,CAAC,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI;IAa/C,SAAS,CAAC,kBAAkB,IAAI,IAAI;IAKpC;;oFAEgF;IAChF,SAAS,CAAC,oBAAoB,IAAI,WAAW;IAa7C;sEACkE;IAClE,SAAS,KAAK,YAAY,IAAI,MAAM,CAEnC;IAED;;;;;OAKG;IACH,SAAS,KAAK,sBAAsB,IAAI,sBAAsB,GAAG,SAAS,CAGzE;CACH"}
1
+ {"version":3,"file":"diagram-widget.d.ts","sourceRoot":"","sources":["../../src/browser/diagram-widget.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAGlF,OAAO,EAAE,iBAAiB,EAAE,KAAK,wBAAwB,EAAE,MAAM,iCAAiC,CAAC;AAGnG,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EAAE,KAAK,SAAS,EAAc,MAAM,8BAA8B,CAAC;AAC1E,OAAO,EAAE,KAAK,kBAAkB,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AAKnF,OAAO,iCAAiC,CAAC;AAEzC,8EAA8E;AAC9E,eAAO,MAAM,qBAAqB,8BAA8B,CAAC;AAEjE;kFACkF;AAClF,eAAO,MAAM,4BAA4B,qCAAoC,CAAC;AAE9E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,qBACa,0BAA2B,SAAQ,iBAAiB;IAC9D,SAAS,CAAC,cAAc,CAAC,EAAE,WAAW,CAAC;IAEvC;;;;OAIG;IACM,SAAS,CAAC,OAAO,EAAE,wBAAwB,EAAE,WAAW,EAAE,SAAS,GAAG,IAAI;IAOnF,kFAAkF;IAClF,SAAS,CAAC,cAAc,IAAI,iBAAiB,CAAC,UAAU,CAAC;cAItC,aAAa,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI;IAO3C,OAAO,IAAI,IAAI;IAKxB;;;;;;;OAOG;IACH,SAAS,CAAC,kBAAkB,IAAI,IAAI;IAmBpC;;;;;;OAMG;IACH,SAAS,CAAC,aAAa,CAAC,OAAO,EAAE,kBAAkB,GAAG,IAAI;IAQ1D;;;;;;;;;OASG;IACH,SAAS,CAAC,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI;IAa/C,SAAS,CAAC,kBAAkB,IAAI,IAAI;IAKpC;;oFAEgF;IAChF,SAAS,CAAC,oBAAoB,IAAI,WAAW;IAa7C;sEACkE;IAClE,SAAS,KAAK,YAAY,IAAI,MAAM,CAEnC;IAED;;;;;OAKG;IACH,SAAS,KAAK,sBAAsB,IAAI,sBAAsB,GAAG,SAAS,CAGzE;CACH"}
@@ -19,6 +19,7 @@ const client_1 = require("@eclipse-glsp/client");
19
19
  const theia_integration_1 = require("@eclipse-glsp/theia-integration");
20
20
  const inversify_1 = require("@theia/core/shared/inversify");
21
21
  const diagram_loader_1 = require("./diagram-loader");
22
+ const glsp_saveable_1 = require("./glsp-saveable");
22
23
  // Shipped by this package rather than left to adopters: an overlay whose
23
24
  // stylesheet was forgotten is an unstyled div in normal flow, which is a silent
24
25
  // failure. Adopters override individual rules from their own stylesheet.
@@ -58,9 +59,27 @@ exports.DIAGRAM_LOADING_FAILED_CLASS = `${exports.DIAGRAM_LOADING_CLASS}-failed`
58
59
  * Bound unconditionally by `AbstractHydraniumGlspTheiaFrontendModule`. To opt out,
59
60
  * override {@link showLoadingOverlay} to a no-op; to change what is rendered,
60
61
  * override {@link createLoadingOverlay} or {@link loadingLabel}.
62
+ *
63
+ * Its saveable is a {@link HydraniumGlspSaveable}, which keeps a pending save
64
+ * dirty, so Theia's exit check still counts it; see {@link createSaveable}.
61
65
  */
62
66
  let HydraniumGlspDiagramWidget = class HydraniumGlspDiagramWidget extends theia_integration_1.GLSPDiagramWidget {
63
67
  loadingOverlay;
68
+ /**
69
+ * Replaces the saveable GLSP's `configure` builds inline, with no factory
70
+ * seam. The widget factory calls `configure` before the widget reaches the
71
+ * shell, so Theia only ever tracks this one.
72
+ */
73
+ configure(options, diContainer) {
74
+ super.configure(options, diContainer);
75
+ this.saveable.dispose();
76
+ this.saveable = this.createSaveable();
77
+ this.toDispose.push(this.saveable);
78
+ }
79
+ /** The widget's saveable. Override to change how saves and dirty state behave. */
80
+ createSaveable() {
81
+ return new glsp_saveable_1.HydraniumGlspSaveable(this.actionDispatcher, this.diContainer.get(client_1.EditorContextService));
82
+ }
64
83
  onAfterAttach(msg) {
65
84
  // Before `super`, which is what starts the load on first attach — so the
66
85
  // overlay is already up when the round trip begins.
@@ -1 +1 @@
1
- {"version":3,"file":"diagram-widget.js","sourceRoot":"","sources":["../../src/browser/diagram-widget.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"diagram-widget.js","sourceRoot":"","sources":["../../src/browser/diagram-widget.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,66 @@
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 { GLSPSaveable } from '@eclipse-glsp/theia-integration/lib/browser/diagram/glsp-saveable';
10
+ /**
11
+ * A `GLSPSaveable` whose every save is a request the server answers, and which
12
+ * stays dirty until that answer arrives.
13
+ *
14
+ * GLSP's sends a `SaveModelAction`, which the server does not answer. It takes
15
+ * the next dirty-state change to clean as the answer, but the editor context
16
+ * reports a change only when the dirty flag changes: the second of two saves
17
+ * gets no answer, and a failed save gets none either. Here each save sends a
18
+ * `RequestSaveModelAction` and settles on the response to that request only:
19
+ * it resolves when the server has saved, rejects when the server rejects it,
20
+ * and rejects when {@link saveTimeout} runs out. A save sent while another is
21
+ * pending is a request of its own, so an edit made between the two is saved.
22
+ *
23
+ * GLSP's also reports not dirty from the moment it sends a save. Theia's exit
24
+ * check asks only whether anything is dirty, so the window closes over a save
25
+ * the server has not finished, and a page reloaded right after Ctrl+S gives no
26
+ * warning. Here the saveable is dirty while any save is pending. GLSP's also
27
+ * gives up after 2 s, and Theia's Save All then counts the save as failed and
28
+ * closes the window anyway, so a slow save of a large model is cut off.
29
+ *
30
+ * The dirty flag still comes from the server. An edit whose dirty-state change
31
+ * has not arrived when Save All runs does not make the saveable dirty, so that
32
+ * edit is not saved.
33
+ *
34
+ * The server answers only where the diagram module registers the request's
35
+ * handler; `AbstractHydraniumGlspDiagramModule` does. A server without it does
36
+ * not advertise the request, and against such a server the saveable is GLSP's:
37
+ * it sends a `SaveModelAction` and reports dirty as GLSP's does. It does not
38
+ * keep only the dirty-while-pending half there, because GLSP's tracks one
39
+ * pending save and a second save overwrites it, so the first would never
40
+ * report clean.
41
+ *
42
+ * The answer means the server has done what its save does, which is not always
43
+ * the disk write: under the `fire-and-forget` `SaveDeliveryPolicy` the server
44
+ * answers before the write finishes and answers a failed write as saved, so a
45
+ * window closed on that answer can still lose the write.
46
+ */
47
+ export declare class HydraniumGlspSaveable extends GLSPSaveable {
48
+ /**
49
+ * How long a save waits for the server's response before it rejects.
50
+ * Long, because the wait only runs out when the server hangs, and a save
51
+ * that rejects in Theia's Save All lets the window close over it.
52
+ */
53
+ protected saveTimeout: number;
54
+ /** The saves sent and not yet settled. */
55
+ protected readonly pendingSaves: Set<Promise<void>>;
56
+ get dirty(): boolean;
57
+ save(): Promise<void>;
58
+ /**
59
+ * Whether the server answers a {@link RequestSaveModelAction}. GLSP's model
60
+ * source registers a handler for each kind the server advertises before it
61
+ * requests the model, so the dispatcher knows it from the first save on.
62
+ */
63
+ protected serverAnswersSaves(): boolean;
64
+ protected sendSave(): Promise<void>;
65
+ }
66
+ //# sourceMappingURL=glsp-saveable.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"glsp-saveable.d.ts","sourceRoot":"","sources":["../../src/browser/glsp-saveable.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAMlF,OAAO,EAAE,YAAY,EAAE,MAAM,mEAAmE,CAAC;AAEjG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,qBAAa,qBAAsB,SAAQ,YAAY;IACpD;;;;OAIG;IACH,UAAmB,WAAW,SAAU;IACxC,0CAA0C;IAC1C,SAAS,CAAC,QAAQ,CAAC,YAAY,qBAA4B;IAE3D,IAAa,KAAK,IAAI,OAAO,CAK5B;IAEQ,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAW9B;;;;OAIG;IACH,SAAS,CAAC,kBAAkB,IAAI,OAAO;IAIvC,SAAS,CAAC,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;CAoBrC"}
@@ -0,0 +1,109 @@
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
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ exports.HydraniumGlspSaveable = void 0;
12
+ const protocol_1 = require("@hydranium/protocol");
13
+ // The module path, not the package root: the root also loads GLSP's diagram
14
+ // widget, which touches DOM globals at module load, and this module's unit tests
15
+ // load it in Node.
16
+ const glsp_saveable_1 = require("@eclipse-glsp/theia-integration/lib/browser/diagram/glsp-saveable");
17
+ /**
18
+ * A `GLSPSaveable` whose every save is a request the server answers, and which
19
+ * stays dirty until that answer arrives.
20
+ *
21
+ * GLSP's sends a `SaveModelAction`, which the server does not answer. It takes
22
+ * the next dirty-state change to clean as the answer, but the editor context
23
+ * reports a change only when the dirty flag changes: the second of two saves
24
+ * gets no answer, and a failed save gets none either. Here each save sends a
25
+ * `RequestSaveModelAction` and settles on the response to that request only:
26
+ * it resolves when the server has saved, rejects when the server rejects it,
27
+ * and rejects when {@link saveTimeout} runs out. A save sent while another is
28
+ * pending is a request of its own, so an edit made between the two is saved.
29
+ *
30
+ * GLSP's also reports not dirty from the moment it sends a save. Theia's exit
31
+ * check asks only whether anything is dirty, so the window closes over a save
32
+ * the server has not finished, and a page reloaded right after Ctrl+S gives no
33
+ * warning. Here the saveable is dirty while any save is pending. GLSP's also
34
+ * gives up after 2 s, and Theia's Save All then counts the save as failed and
35
+ * closes the window anyway, so a slow save of a large model is cut off.
36
+ *
37
+ * The dirty flag still comes from the server. An edit whose dirty-state change
38
+ * has not arrived when Save All runs does not make the saveable dirty, so that
39
+ * edit is not saved.
40
+ *
41
+ * The server answers only where the diagram module registers the request's
42
+ * handler; `AbstractHydraniumGlspDiagramModule` does. A server without it does
43
+ * not advertise the request, and against such a server the saveable is GLSP's:
44
+ * it sends a `SaveModelAction` and reports dirty as GLSP's does. It does not
45
+ * keep only the dirty-while-pending half there, because GLSP's tracks one
46
+ * pending save and a second save overwrites it, so the first would never
47
+ * report clean.
48
+ *
49
+ * The answer means the server has done what its save does, which is not always
50
+ * the disk write: under the `fire-and-forget` `SaveDeliveryPolicy` the server
51
+ * answers before the write finishes and answers a failed write as saved, so a
52
+ * window closed on that answer can still lose the write.
53
+ */
54
+ class HydraniumGlspSaveable extends glsp_saveable_1.GLSPSaveable {
55
+ /**
56
+ * How long a save waits for the server's response before it rejects.
57
+ * Long, because the wait only runs out when the server hangs, and a save
58
+ * that rejects in Theia's Save All lets the window close over it.
59
+ */
60
+ saveTimeout = 10_000;
61
+ /** The saves sent and not yet settled. */
62
+ pendingSaves = new Set();
63
+ get dirty() {
64
+ if (!this.serverAnswersSaves()) {
65
+ return super.dirty;
66
+ }
67
+ return this.editorContextService.isDirty || this.pendingSaves.size > 0;
68
+ }
69
+ save() {
70
+ if (!this.serverAnswersSaves()) {
71
+ return super.save();
72
+ }
73
+ if (this.editorContextService.isDirty) {
74
+ return this.sendSave();
75
+ }
76
+ // Nothing new to save, but a save still pending has not finished.
77
+ return Promise.all(this.pendingSaves).then(() => undefined);
78
+ }
79
+ /**
80
+ * Whether the server answers a {@link RequestSaveModelAction}. GLSP's model
81
+ * source registers a handler for each kind the server advertises before it
82
+ * requests the model, so the dispatcher knows it from the first save on.
83
+ */
84
+ serverAnswersSaves() {
85
+ return this.actionDispatcher.hasHandler(protocol_1.RequestSaveModelAction.create());
86
+ }
87
+ sendSave() {
88
+ // `request` with a bound of our own rather than GLSP's `requestUntil`:
89
+ // that one forgets a request when it times out, so a late response is
90
+ // dispatched as an action no client handler takes, which rejects.
91
+ // Here a late response settles the forgotten request and nothing else.
92
+ const response = this.actionDispatcher.request(protocol_1.RequestSaveModelAction.create());
93
+ let timer;
94
+ const timedOut = new Promise((_resolve, reject) => {
95
+ timer = setTimeout(() => reject(new Error('Save operation timed out')), this.saveTimeout);
96
+ });
97
+ const saving = Promise.race([response, timedOut])
98
+ .then(() => undefined)
99
+ .finally(() => {
100
+ clearTimeout(timer);
101
+ this.pendingSaves.delete(saving);
102
+ this.onDirtyChangedEmitter.fire(undefined);
103
+ });
104
+ this.pendingSaves.add(saving);
105
+ return saving;
106
+ }
107
+ }
108
+ exports.HydraniumGlspSaveable = HydraniumGlspSaveable;
109
+ //# sourceMappingURL=glsp-saveable.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"glsp-saveable.js","sourceRoot":"","sources":["../../src/browser/glsp-saveable.ts"],"names":[],"mappings":";AAAA;;;;;;;kFAOkF;;;AAElF,kDAA6D;AAC7D,4EAA4E;AAC5E,iFAAiF;AACjF,mBAAmB;AACnB,qGAAiG;AAEjG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,MAAa,qBAAsB,SAAQ,4BAAY;IACpD;;;;OAIG;IACgB,WAAW,GAAG,MAAM,CAAC;IACxC,0CAA0C;IACvB,YAAY,GAAG,IAAI,GAAG,EAAiB,CAAC;IAE3D,IAAa,KAAK;QACf,IAAI,CAAC,IAAI,CAAC,kBAAkB,EAAE,EAAE,CAAC;YAC9B,OAAO,KAAK,CAAC,KAAK,CAAC;QACtB,CAAC;QACD,OAAO,IAAI,CAAC,oBAAoB,CAAC,OAAO,IAAI,IAAI,CAAC,YAAY,CAAC,IAAI,GAAG,CAAC,CAAC;IAC1E,CAAC;IAEQ,IAAI;QACV,IAAI,CAAC,IAAI,CAAC,kBAAkB,EAAE,EAAE,CAAC;YAC9B,OAAO,KAAK,CAAC,IAAI,EAAE,CAAC;QACvB,CAAC;QACD,IAAI,IAAI,CAAC,oBAAoB,CAAC,OAAO,EAAE,CAAC;YACrC,OAAO,IAAI,CAAC,QAAQ,EAAE,CAAC;QAC1B,CAAC;QACD,kEAAkE;QAClE,OAAO,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;IAC/D,CAAC;IAED;;;;OAIG;IACO,kBAAkB;QACzB,OAAO,IAAI,CAAC,gBAAgB,CAAC,UAAU,CAAC,iCAAsB,CAAC,MAAM,EAAE,CAAC,CAAC;IAC5E,CAAC;IAES,QAAQ;QACf,uEAAuE;QACvE,sEAAsE;QACtE,kEAAkE;QAClE,uEAAuE;QACvE,MAAM,QAAQ,GAAG,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAAC,iCAAsB,CAAC,MAAM,EAAE,CAAC,CAAC;QAChF,IAAI,KAAgD,CAAC;QACrD,MAAM,QAAQ,GAAG,IAAI,OAAO,CAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE;YACtD,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAC,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;QAC7F,CAAC,CAAC,CAAC;QACH,MAAM,MAAM,GAAkB,OAAO,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;aAC5D,IAAI,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC;aACrB,OAAO,CAAC,GAAG,EAAE;YACX,YAAY,CAAC,KAAK,CAAC,CAAC;YACpB,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;YACjC,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAC9C,CAAC,CAAC,CAAC;QACN,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAC9B,OAAO,MAAM,CAAC;IACjB,CAAC;CACH;AAzDD,sDAyDC"}
@@ -8,7 +8,7 @@
8
8
  ********************************************************************************/
9
9
  import { type Action, type ElementAndRoutingPoints, type GModelElement, type GRoutableElement, GLSPHiddenBoundsUpdater, RequestBoundsAction } from '@eclipse-glsp/client';
10
10
  import { ChannelLogger } from '@hydranium/client-theia/lib/browser';
11
- import { type Clock } from '@hydranium/protocol';
11
+ import { Clock } from '@hydranium/client-theia/lib/common';
12
12
  import { type VNode } from 'snabbdom';
13
13
  /**
14
14
  * Instruments sprotty's hidden-bounds pass and repairs degenerate routes before
@@ -50,9 +50,7 @@ import { type VNode } from 'snabbdom';
50
50
  */
51
51
  export declare class HydraniumHiddenBoundsUpdater extends GLSPHiddenBoundsUpdater {
52
52
  protected readonly channel: ChannelLogger;
53
- /** Not injected: the browser container binds no {@link Clock}, and this only
54
- * measures — no logic is gated on time, so there is nothing to fake in
55
- * production. Overridden in tests for a deterministic elapsed value. */
53
+ /** The diagram container's {@link Clock}, or a `SystemClock`; it only measures. */
56
54
  protected readonly clock: Clock;
57
55
  /**
58
56
  * Scope description for the in-flight request, read from the `cause` in
@@ -1 +1 @@
1
- {"version":3,"file":"hidden-bounds-updater.d.ts","sourceRoot":"","sources":["../../src/browser/hidden-bounds-updater.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAElF,OAAO,EACJ,KAAK,MAAM,EACX,KAAK,uBAAuB,EAC5B,KAAK,aAAa,EAClB,KAAK,gBAAgB,EACrB,uBAAuB,EAGvB,mBAAmB,EAGrB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,aAAa,EAAE,MAAM,qCAAqC,CAAC;AACpE,OAAO,EAAE,KAAK,KAAK,EAAe,MAAM,qBAAqB,CAAC;AAE9D,OAAO,EAAE,KAAK,KAAK,EAAE,MAAM,UAAU,CAAC;AAOtC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,qBACa,4BAA6B,SAAQ,uBAAuB;IAC/C,SAAS,CAAC,QAAQ,CAAC,OAAO,EAAG,aAAa,CAAC;IAElE;;6EAEyE;IACzE,SAAS,CAAC,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAqB;IAEpD;;;;OAIG;IACH,SAAS,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAEvB,QAAQ,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,aAAa,GAAG,KAAK;IAQ9D;;;;;;;;;;;;;;;;OAgBG;IACH,SAAS,CAAC,eAAe,CAAC,OAAO,EAAE,gBAAgB,GAAG,IAAI;IAQ1D,2EAA2E;IAC3E,SAAS,CAAC,aAAa,CAAC,KAAK,EAAE,uBAAuB,GAAG,OAAO;IAIhE;uEACmE;IACnE,SAAS,CAAC,mBAAmB,CAAC,OAAO,EAAE,gBAAgB,GAAG,uBAAuB;cAO9D,gBAAgB,IAAI,IAAI;IAa3C,mEAAmE;IACnE,SAAS,CAAC,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM;IAIhF,UAAU,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI;IAazC;;;;;;;;;;;OAWG;IACH,SAAS,CAAC,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;IAM5C;;;;;;;;;;;;;;;OAeG;IACH,SAAS,CAAC,WAAW,CAAC,KAAK,EAAE,mBAAmB,GAAG,MAAM,GAAG,SAAS;CAcvE"}
1
+ {"version":3,"file":"hidden-bounds-updater.d.ts","sourceRoot":"","sources":["../../src/browser/hidden-bounds-updater.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAElF,OAAO,EACJ,KAAK,MAAM,EACX,KAAK,uBAAuB,EAC5B,KAAK,aAAa,EAClB,KAAK,gBAAgB,EACrB,uBAAuB,EAGvB,mBAAmB,EAGrB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,aAAa,EAAE,MAAM,qCAAqC,CAAC;AACpE,OAAO,EAAE,KAAK,EAAE,MAAM,oCAAoC,CAAC;AAG3D,OAAO,EAAE,KAAK,KAAK,EAAE,MAAM,UAAU,CAAC;AAOtC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,qBACa,4BAA6B,SAAQ,uBAAuB;IAC/C,SAAS,CAAC,QAAQ,CAAC,OAAO,EAAG,aAAa,CAAC;IAElE,mFAAmF;IACxD,SAAS,CAAC,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAqB;IAE/E;;;;OAIG;IACH,SAAS,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAEvB,QAAQ,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,aAAa,GAAG,KAAK;IAQ9D;;;;;;;;;;;;;;;;OAgBG;IACH,SAAS,CAAC,eAAe,CAAC,OAAO,EAAE,gBAAgB,GAAG,IAAI;IAQ1D,2EAA2E;IAC3E,SAAS,CAAC,aAAa,CAAC,KAAK,EAAE,uBAAuB,GAAG,OAAO;IAIhE;uEACmE;IACnE,SAAS,CAAC,mBAAmB,CAAC,OAAO,EAAE,gBAAgB,GAAG,uBAAuB;cAO9D,gBAAgB,IAAI,IAAI;IAa3C,mEAAmE;IACnE,SAAS,CAAC,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM;IAIhF,UAAU,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI;IAazC;;;;;;;;;;;OAWG;IACH,SAAS,CAAC,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;IAM5C;;;;;;;;;;;;;;;OAeG;IACH,SAAS,CAAC,WAAW,CAAC,KAAK,EAAE,mBAAmB,GAAG,MAAM,GAAG,SAAS;CAcvE"}
@@ -20,6 +20,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
20
20
  exports.HydraniumHiddenBoundsUpdater = void 0;
21
21
  const client_1 = require("@eclipse-glsp/client");
22
22
  const browser_1 = require("@hydranium/client-theia/lib/browser");
23
+ const common_1 = require("@hydranium/client-theia/lib/common");
23
24
  const protocol_1 = require("@hydranium/protocol");
24
25
  const inversify_1 = require("@theia/core/shared/inversify");
25
26
  /** How many scoped element ids the log line names before summarising the rest.
@@ -66,9 +67,7 @@ const SCOPE_ID_CAP = 3;
66
67
  */
67
68
  let HydraniumHiddenBoundsUpdater = class HydraniumHiddenBoundsUpdater extends client_1.GLSPHiddenBoundsUpdater {
68
69
  channel;
69
- /** Not injected: the browser container binds no {@link Clock}, and this only
70
- * measures — no logic is gated on time, so there is nothing to fake in
71
- * production. Overridden in tests for a deterministic elapsed value. */
70
+ /** The diagram container's {@link Clock}, or a `SystemClock`; it only measures. */
72
71
  clock = new protocol_1.SystemClock();
73
72
  /**
74
73
  * Scope description for the in-flight request, read from the `cause` in
@@ -201,6 +200,11 @@ __decorate([
201
200
  (0, inversify_1.inject)(browser_1.ChannelLogger),
202
201
  __metadata("design:type", browser_1.ChannelLogger)
203
202
  ], HydraniumHiddenBoundsUpdater.prototype, "channel", void 0);
203
+ __decorate([
204
+ (0, inversify_1.inject)(common_1.Clock),
205
+ (0, inversify_1.optional)(),
206
+ __metadata("design:type", Object)
207
+ ], HydraniumHiddenBoundsUpdater.prototype, "clock", void 0);
204
208
  exports.HydraniumHiddenBoundsUpdater = HydraniumHiddenBoundsUpdater = __decorate([
205
209
  (0, inversify_1.injectable)()
206
210
  ], HydraniumHiddenBoundsUpdater);
@@ -1 +1 @@
1
- {"version":3,"file":"hidden-bounds-updater.js","sourceRoot":"","sources":["../../src/browser/hidden-bounds-updater.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"hidden-bounds-updater.js","sourceRoot":"","sources":["../../src/browser/hidden-bounds-updater.ts"],"names":[],"mappings":"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"}
@@ -14,6 +14,7 @@ export * from './diagram-widget';
14
14
  export * from './glsp-client-theia-module';
15
15
  export * from './glsp-diagram-manager';
16
16
  export * from './glsp-message-service';
17
+ export * from './glsp-saveable';
17
18
  export * from './glsp-theia-frontend-module';
18
19
  export * from './hidden-bounds-updater';
19
20
  export * from './hydranium-glsp-diagram-configuration';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/browser/index.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAIlF,cAAc,qBAAqB,CAAC;AACpC,cAAc,uBAAuB,CAAC;AACtC,cAAc,kBAAkB,CAAC;AACjC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,kBAAkB,CAAC;AACjC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,yBAAyB,CAAC;AACxC,cAAc,wCAAwC,CAAC;AAKvD,YAAY,EAAE,mBAAmB,EAAE,MAAM,4CAA4C,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/browser/index.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAIlF,cAAc,qBAAqB,CAAC;AACpC,cAAc,uBAAuB,CAAC;AACtC,cAAc,kBAAkB,CAAC;AACjC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,kBAAkB,CAAC;AACjC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,iBAAiB,CAAC;AAChC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,yBAAyB,CAAC;AACxC,cAAc,wCAAwC,CAAC;AAKvD,YAAY,EAAE,mBAAmB,EAAE,MAAM,4CAA4C,CAAC"}
@@ -32,6 +32,7 @@ __exportStar(require("./diagram-widget"), exports);
32
32
  __exportStar(require("./glsp-client-theia-module"), exports);
33
33
  __exportStar(require("./glsp-diagram-manager"), exports);
34
34
  __exportStar(require("./glsp-message-service"), exports);
35
+ __exportStar(require("./glsp-saveable"), exports);
35
36
  __exportStar(require("./glsp-theia-frontend-module"), exports);
36
37
  __exportStar(require("./hidden-bounds-updater"), exports);
37
38
  __exportStar(require("./hydranium-glsp-diagram-configuration"), exports);
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/browser/index.ts"],"names":[],"mappings":";AAAA;;;;;;;kFAOkF;;;;;;;;;;;;;;;;AAElF,gEAAgE;AAChE,mFAAmF;AACnF,sDAAoC;AACpC,wDAAsC;AACtC,mDAAiC;AACjC,gEAA8C;AAC9C,mDAAiC;AACjC,6DAA2C;AAC3C,yDAAuC;AACvC,yDAAuC;AACvC,+DAA6C;AAC7C,0DAAwC;AACxC,yEAAuD"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/browser/index.ts"],"names":[],"mappings":";AAAA;;;;;;;kFAOkF;;;;;;;;;;;;;;;;AAElF,gEAAgE;AAChE,mFAAmF;AACnF,sDAAoC;AACpC,wDAAsC;AACtC,mDAAiC;AACjC,gEAA8C;AAC9C,mDAAiC;AACjC,6DAA2C;AAC3C,yDAAuC;AACvC,yDAAuC;AACvC,kDAAgC;AAChC,+DAA6C;AAC7C,0DAAwC;AACxC,yEAAuD"}
@@ -7,7 +7,6 @@
7
7
  * SPDX-License-Identifier: MIT
8
8
  ********************************************************************************/
9
9
  import { AbstractSocketForwardingConnectionHandler } from '@hydranium/client-theia/lib/node';
10
- import { type Channel, type Disposable } from '@theia/core';
11
10
  import type * as net from 'net';
12
11
  /** Options for `GlspServerConnectionHandler`. The language contribution
13
12
  * id determines the per-language servicePath that Theia routes browser-frontend
@@ -42,18 +41,15 @@ export interface GlspServerConnectionHandlerOptions {
42
41
  /**
43
42
  * Bridges a Theia browser-frontend channel to a GLSP server's TCP socket.
44
43
  *
45
- * The port-discovery + buffer-and-replay race fix + connect orchestration live
46
- * on the cross-head {@link AbstractSocketForwardingConnectionHandler} base; this
47
- * subclass supplies only the GLSP specifics — the per-language servicePath
44
+ * The port discovery, the buffer-and-replay race fix, the connect orchestration
45
+ * and the byte forwarder live on the cross-head
46
+ * {@link AbstractSocketForwardingConnectionHandler} base; this subclass supplies
47
+ * only the GLSP specifics — the per-language servicePath
48
48
  * (`GLSPContribution.servicePath + '/' + languageContributionId`), the port
49
- * command, the log labels — and plugs in `@eclipse-glsp/theia-integration`'s
50
- * `SocketConnectionForwarder` as the byte relay. Adopters with different
51
- * language ids or command names subclass with a one-line `super({...})` call.
52
- * Sibling of `@hydranium/data-client-theia`'s `DataServerConnectionHandler`,
53
- * which subclasses the same base with its own GLSP-free forwarder.
49
+ * command, the log labels. Adopters with different language ids or command
50
+ * names subclass with a one-line `super({...})` call.
54
51
  */
55
52
  export declare class GlspServerConnectionHandler extends AbstractSocketForwardingConnectionHandler {
56
53
  constructor(options: GlspServerConnectionHandlerOptions);
57
- protected forwardToSocketConnection(clientChannel: Channel, socket: net.Socket): Disposable;
58
54
  }
59
55
  //# sourceMappingURL=glsp-server-connection-handler.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"glsp-server-connection-handler.d.ts","sourceRoot":"","sources":["../../src/node/glsp-server-connection-handler.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAIlF,OAAO,EAAE,yCAAyC,EAAE,MAAM,kCAAkC,CAAC;AAC7F,OAAO,EAAE,KAAK,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,aAAa,CAAC;AAE5D,OAAO,KAAK,KAAK,GAAG,MAAM,KAAK,CAAC;AAEhC;;;iDAGiD;AACjD,MAAM,WAAW,kCAAkC;IAChD,QAAQ,CAAC,sBAAsB,EAAE,MAAM,CAAC;IACxC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B;;;;;;;;OAQG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IACnC;;;;;;;OAOG;IACH,QAAQ,CAAC,eAAe,CAAC,EAAE,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,KAAK,IAAI,CAAC;CAC1D;AAED;;;;;;;;;;;;GAYG;AACH,qBACa,2BAA4B,SAAQ,yCAAyC;gBAC9D,OAAO,EAAE,kCAAkC;IAapE,SAAS,CAAC,yBAAyB,CAAC,aAAa,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,GAAG,UAAU;CAG7F"}
1
+ {"version":3,"file":"glsp-server-connection-handler.d.ts","sourceRoot":"","sources":["../../src/node/glsp-server-connection-handler.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAGlF,OAAO,EAAE,yCAAyC,EAAE,MAAM,kCAAkC,CAAC;AAE7F,OAAO,KAAK,KAAK,GAAG,MAAM,KAAK,CAAC;AAEhC;;;iDAGiD;AACjD,MAAM,WAAW,kCAAkC;IAChD,QAAQ,CAAC,sBAAsB,EAAE,MAAM,CAAC;IACxC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B;;;;;;;;OAQG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IACnC;;;;;;;OAOG;IACH,QAAQ,CAAC,eAAe,CAAC,EAAE,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,KAAK,IAAI,CAAC;CAC1D;AAED;;;;;;;;;;GAUG;AACH,qBACa,2BAA4B,SAAQ,yCAAyC;gBAC9D,OAAO,EAAE,kCAAkC;CAYtE"}
@@ -22,23 +22,20 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
22
22
  Object.defineProperty(exports, "__esModule", { value: true });
23
23
  exports.GlspServerConnectionHandler = void 0;
24
24
  const common_1 = require("@eclipse-glsp/theia-integration/lib/common");
25
- const node_1 = require("@eclipse-glsp/theia-integration/lib/node");
26
- const node_2 = require("@hydranium/client-theia/lib/node");
25
+ const node_1 = require("@hydranium/client-theia/lib/node");
27
26
  const inversify_1 = require("@theia/core/shared/inversify");
28
27
  /**
29
28
  * Bridges a Theia browser-frontend channel to a GLSP server's TCP socket.
30
29
  *
31
- * The port-discovery + buffer-and-replay race fix + connect orchestration live
32
- * on the cross-head {@link AbstractSocketForwardingConnectionHandler} base; this
33
- * subclass supplies only the GLSP specifics — the per-language servicePath
30
+ * The port discovery, the buffer-and-replay race fix, the connect orchestration
31
+ * and the byte forwarder live on the cross-head
32
+ * {@link AbstractSocketForwardingConnectionHandler} base; this subclass supplies
33
+ * only the GLSP specifics — the per-language servicePath
34
34
  * (`GLSPContribution.servicePath + '/' + languageContributionId`), the port
35
- * command, the log labels — and plugs in `@eclipse-glsp/theia-integration`'s
36
- * `SocketConnectionForwarder` as the byte relay. Adopters with different
37
- * language ids or command names subclass with a one-line `super({...})` call.
38
- * Sibling of `@hydranium/data-client-theia`'s `DataServerConnectionHandler`,
39
- * which subclasses the same base with its own GLSP-free forwarder.
35
+ * command, the log labels. Adopters with different language ids or command
36
+ * names subclass with a one-line `super({...})` call.
40
37
  */
41
- let GlspServerConnectionHandler = class GlspServerConnectionHandler extends node_2.AbstractSocketForwardingConnectionHandler {
38
+ let GlspServerConnectionHandler = class GlspServerConnectionHandler extends node_1.AbstractSocketForwardingConnectionHandler {
42
39
  constructor(options) {
43
40
  super({
44
41
  path: common_1.GLSPContribution.servicePath + '/' + options.languageContributionId,
@@ -51,9 +48,6 @@ let GlspServerConnectionHandler = class GlspServerConnectionHandler extends node
51
48
  onSocketCreated: options.onSocketCreated
52
49
  });
53
50
  }
54
- forwardToSocketConnection(clientChannel, socket) {
55
- return new node_1.SocketConnectionForwarder(clientChannel, socket);
56
- }
57
51
  };
58
52
  exports.GlspServerConnectionHandler = GlspServerConnectionHandler;
59
53
  exports.GlspServerConnectionHandler = GlspServerConnectionHandler = __decorate([
@@ -1 +1 @@
1
- {"version":3,"file":"glsp-server-connection-handler.js","sourceRoot":"","sources":["../../src/node/glsp-server-connection-handler.ts"],"names":[],"mappings":";AAAA;;;;;;;kFAOkF;;;;;;;;;;;;;;;AAElF,uEAA8E;AAC9E,mEAAqF;AACrF,2DAA6F;AAE7F,4DAAqE;AAkCrE;;;;;;;;;;;;GAYG;AAEI,IAAM,2BAA2B,GAAjC,MAAM,2BAA4B,SAAQ,gDAAyC;IACvF,YAAyB,OAA2C;QACjE,KAAK,CAAC;YACH,IAAI,EAAE,yBAAgB,CAAC,WAAW,GAAG,GAAG,GAAG,OAAO,CAAC,sBAAsB;YACzE,WAAW,EAAE,OAAO,CAAC,WAAW;YAChC,YAAY,EAAE,MAAM;YACpB,UAAU,EAAE,OAAO,CAAC,UAAU,IAAI,kBAAkB;YACpD,eAAe,EAAE,OAAO,CAAC,eAAe;YACxC,gBAAgB,EAAE,OAAO,CAAC,gBAAgB;YAC1C,gBAAgB,EAAE,OAAO,CAAC,gBAAgB;YAC1C,eAAe,EAAE,OAAO,CAAC,eAAe;SAC1C,CAAC,CAAC;IACN,CAAC;IAES,yBAAyB,CAAC,aAAsB,EAAE,MAAkB;QAC3E,OAAO,IAAI,gCAAyB,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC;IAC/D,CAAC;CACH,CAAA;AAjBY,kEAA2B;sCAA3B,2BAA2B;IADvC,IAAA,sBAAU,GAAE;IAEG,WAAA,IAAA,qBAAS,GAAE,CAAA;;GADd,2BAA2B,CAiBvC"}
1
+ {"version":3,"file":"glsp-server-connection-handler.js","sourceRoot":"","sources":["../../src/node/glsp-server-connection-handler.ts"],"names":[],"mappings":";AAAA;;;;;;;kFAOkF;;;;;;;;;;;;;;;AAElF,uEAA8E;AAC9E,2DAA6F;AAC7F,4DAAqE;AAkCrE;;;;;;;;;;GAUG;AAEI,IAAM,2BAA2B,GAAjC,MAAM,2BAA4B,SAAQ,gDAAyC;IACvF,YAAyB,OAA2C;QACjE,KAAK,CAAC;YACH,IAAI,EAAE,yBAAgB,CAAC,WAAW,GAAG,GAAG,GAAG,OAAO,CAAC,sBAAsB;YACzE,WAAW,EAAE,OAAO,CAAC,WAAW;YAChC,YAAY,EAAE,MAAM;YACpB,UAAU,EAAE,OAAO,CAAC,UAAU,IAAI,kBAAkB;YACpD,eAAe,EAAE,OAAO,CAAC,eAAe;YACxC,gBAAgB,EAAE,OAAO,CAAC,gBAAgB;YAC1C,gBAAgB,EAAE,OAAO,CAAC,gBAAgB;YAC1C,eAAe,EAAE,OAAO,CAAC,eAAe;SAC1C,CAAC,CAAC;IACN,CAAC;CACH,CAAA;AAbY,kEAA2B;sCAA3B,2BAA2B;IADvC,IAAA,sBAAU,GAAE;IAEG,WAAA,IAAA,qBAAS,GAAE,CAAA;;GADd,2BAA2B,CAavC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hydranium/glsp-client-theia",
3
- "version": "1.0.0-next.123",
3
+ "version": "1.0.0-next.127",
4
4
  "description": "Theia-coupled client primitives for GLSP heads built on @hydranium/glsp-server. Provides the action dispatcher, channel logger, and connection-handler bases that Theia-based adopters extend; companion of @hydranium/glsp-server.",
5
5
  "keywords": [
6
6
  "hydranium",
@@ -77,15 +77,19 @@
77
77
  },
78
78
  "devDependencies": {
79
79
  "@eclipse-glsp/client": "2.7.0",
80
+ "@eclipse-glsp/server": "2.7.0",
80
81
  "@eclipse-glsp/theia-integration": "2.7.0",
81
- "@hydranium/client-theia": "1.0.0-next.123",
82
- "@hydranium/protocol": "1.0.0-next.123",
82
+ "@hydranium/client-theia": "1.0.0-next.127",
83
+ "@hydranium/core": "1.0.0-next.127",
84
+ "@hydranium/glsp-server": "1.0.0-next.127",
85
+ "@hydranium/protocol": "1.0.0-next.127",
83
86
  "@theia/core": "^1.70.0",
84
87
  "@theia/output": "^1.70.0",
85
88
  "@theia/process": "^1.70.0",
86
89
  "@theia/workspace": "^1.70.0",
87
90
  "@types/node": "^22.0.0",
88
91
  "inversify": "6.2.2",
92
+ "reflect-metadata": "0.2.2",
89
93
  "rimraf": "^5.0.0",
90
94
  "snabbdom": "3.5.1",
91
95
  "typescript": "^5.8.0"
@@ -93,8 +97,8 @@
93
97
  "peerDependencies": {
94
98
  "@eclipse-glsp/client": "^2.6.0",
95
99
  "@eclipse-glsp/theia-integration": "^2.6.0",
96
- "@hydranium/client-theia": "1.0.0-next.123",
97
- "@hydranium/protocol": "1.0.0-next.123",
100
+ "@hydranium/client-theia": "1.0.0-next.127",
101
+ "@hydranium/protocol": "1.0.0-next.127",
98
102
  "@theia/core": "^1.70.0",
99
103
  "@theia/output": "^1.70.0",
100
104
  "@theia/process": "^1.70.0",
@@ -7,13 +7,14 @@
7
7
  * SPDX-License-Identifier: MIT
8
8
  ********************************************************************************/
9
9
 
10
- import { DiagramLoader } from '@eclipse-glsp/client';
11
- import { GLSPDiagramWidget } from '@eclipse-glsp/theia-integration';
10
+ import { DiagramLoader, EditorContextService } from '@eclipse-glsp/client';
11
+ import { GLSPDiagramWidget, type GLSPDiagramWidgetOptions } from '@eclipse-glsp/theia-integration';
12
12
  // Type-only: the `@theia/core/lib/browser` barrel touches DOM globals at module
13
13
  // load, which the node-environment unit tests cannot provide.
14
14
  import { type Message } from '@theia/core/lib/browser';
15
- import { injectable } from '@theia/core/shared/inversify';
15
+ import { type Container, injectable } from '@theia/core/shared/inversify';
16
16
  import { type DiagramLoadOutcome, HydraniumDiagramLoader } from './diagram-loader';
17
+ import { HydraniumGlspSaveable } from './glsp-saveable';
17
18
  // Shipped by this package rather than left to adopters: an overlay whose
18
19
  // stylesheet was forgotten is an unstyled div in normal flow, which is a silent
19
20
  // failure. Adopters override individual rules from their own stylesheet.
@@ -56,11 +57,31 @@ export const DIAGRAM_LOADING_FAILED_CLASS = `${DIAGRAM_LOADING_CLASS}-failed`;
56
57
  * Bound unconditionally by `AbstractHydraniumGlspTheiaFrontendModule`. To opt out,
57
58
  * override {@link showLoadingOverlay} to a no-op; to change what is rendered,
58
59
  * override {@link createLoadingOverlay} or {@link loadingLabel}.
60
+ *
61
+ * Its saveable is a {@link HydraniumGlspSaveable}, which keeps a pending save
62
+ * dirty, so Theia's exit check still counts it; see {@link createSaveable}.
59
63
  */
60
64
  @injectable()
61
65
  export class HydraniumGlspDiagramWidget extends GLSPDiagramWidget {
62
66
  protected loadingOverlay?: HTMLElement;
63
67
 
68
+ /**
69
+ * Replaces the saveable GLSP's `configure` builds inline, with no factory
70
+ * seam. The widget factory calls `configure` before the widget reaches the
71
+ * shell, so Theia only ever tracks this one.
72
+ */
73
+ override configure(options: GLSPDiagramWidgetOptions, diContainer: Container): void {
74
+ super.configure(options, diContainer);
75
+ this.saveable.dispose();
76
+ this.saveable = this.createSaveable();
77
+ this.toDispose.push(this.saveable);
78
+ }
79
+
80
+ /** The widget's saveable. Override to change how saves and dirty state behave. */
81
+ protected createSaveable(): GLSPDiagramWidget['saveable'] {
82
+ return new HydraniumGlspSaveable(this.actionDispatcher, this.diContainer.get(EditorContextService));
83
+ }
84
+
64
85
  protected override onAfterAttach(msg: Message): void {
65
86
  // Before `super`, which is what starts the load on first attach — so the
66
87
  // overlay is already up when the round trip begins.
@@ -0,0 +1,110 @@
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
+
10
+ import { RequestSaveModelAction } from '@hydranium/protocol';
11
+ // The module path, not the package root: the root also loads GLSP's diagram
12
+ // widget, which touches DOM globals at module load, and this module's unit tests
13
+ // load it in Node.
14
+ import { GLSPSaveable } from '@eclipse-glsp/theia-integration/lib/browser/diagram/glsp-saveable';
15
+
16
+ /**
17
+ * A `GLSPSaveable` whose every save is a request the server answers, and which
18
+ * stays dirty until that answer arrives.
19
+ *
20
+ * GLSP's sends a `SaveModelAction`, which the server does not answer. It takes
21
+ * the next dirty-state change to clean as the answer, but the editor context
22
+ * reports a change only when the dirty flag changes: the second of two saves
23
+ * gets no answer, and a failed save gets none either. Here each save sends a
24
+ * `RequestSaveModelAction` and settles on the response to that request only:
25
+ * it resolves when the server has saved, rejects when the server rejects it,
26
+ * and rejects when {@link saveTimeout} runs out. A save sent while another is
27
+ * pending is a request of its own, so an edit made between the two is saved.
28
+ *
29
+ * GLSP's also reports not dirty from the moment it sends a save. Theia's exit
30
+ * check asks only whether anything is dirty, so the window closes over a save
31
+ * the server has not finished, and a page reloaded right after Ctrl+S gives no
32
+ * warning. Here the saveable is dirty while any save is pending. GLSP's also
33
+ * gives up after 2 s, and Theia's Save All then counts the save as failed and
34
+ * closes the window anyway, so a slow save of a large model is cut off.
35
+ *
36
+ * The dirty flag still comes from the server. An edit whose dirty-state change
37
+ * has not arrived when Save All runs does not make the saveable dirty, so that
38
+ * edit is not saved.
39
+ *
40
+ * The server answers only where the diagram module registers the request's
41
+ * handler; `AbstractHydraniumGlspDiagramModule` does. A server without it does
42
+ * not advertise the request, and against such a server the saveable is GLSP's:
43
+ * it sends a `SaveModelAction` and reports dirty as GLSP's does. It does not
44
+ * keep only the dirty-while-pending half there, because GLSP's tracks one
45
+ * pending save and a second save overwrites it, so the first would never
46
+ * report clean.
47
+ *
48
+ * The answer means the server has done what its save does, which is not always
49
+ * the disk write: under the `fire-and-forget` `SaveDeliveryPolicy` the server
50
+ * answers before the write finishes and answers a failed write as saved, so a
51
+ * window closed on that answer can still lose the write.
52
+ */
53
+ export class HydraniumGlspSaveable extends GLSPSaveable {
54
+ /**
55
+ * How long a save waits for the server's response before it rejects.
56
+ * Long, because the wait only runs out when the server hangs, and a save
57
+ * that rejects in Theia's Save All lets the window close over it.
58
+ */
59
+ protected override saveTimeout = 10_000;
60
+ /** The saves sent and not yet settled. */
61
+ protected readonly pendingSaves = new Set<Promise<void>>();
62
+
63
+ override get dirty(): boolean {
64
+ if (!this.serverAnswersSaves()) {
65
+ return super.dirty;
66
+ }
67
+ return this.editorContextService.isDirty || this.pendingSaves.size > 0;
68
+ }
69
+
70
+ override save(): Promise<void> {
71
+ if (!this.serverAnswersSaves()) {
72
+ return super.save();
73
+ }
74
+ if (this.editorContextService.isDirty) {
75
+ return this.sendSave();
76
+ }
77
+ // Nothing new to save, but a save still pending has not finished.
78
+ return Promise.all(this.pendingSaves).then(() => undefined);
79
+ }
80
+
81
+ /**
82
+ * Whether the server answers a {@link RequestSaveModelAction}. GLSP's model
83
+ * source registers a handler for each kind the server advertises before it
84
+ * requests the model, so the dispatcher knows it from the first save on.
85
+ */
86
+ protected serverAnswersSaves(): boolean {
87
+ return this.actionDispatcher.hasHandler(RequestSaveModelAction.create());
88
+ }
89
+
90
+ protected sendSave(): Promise<void> {
91
+ // `request` with a bound of our own rather than GLSP's `requestUntil`:
92
+ // that one forgets a request when it times out, so a late response is
93
+ // dispatched as an action no client handler takes, which rejects.
94
+ // Here a late response settles the forgotten request and nothing else.
95
+ const response = this.actionDispatcher.request(RequestSaveModelAction.create());
96
+ let timer: ReturnType<typeof setTimeout> | undefined;
97
+ const timedOut = new Promise<never>((_resolve, reject) => {
98
+ timer = setTimeout(() => reject(new Error('Save operation timed out')), this.saveTimeout);
99
+ });
100
+ const saving: Promise<void> = Promise.race([response, timedOut])
101
+ .then(() => undefined)
102
+ .finally(() => {
103
+ clearTimeout(timer);
104
+ this.pendingSaves.delete(saving);
105
+ this.onDirtyChangedEmitter.fire(undefined);
106
+ });
107
+ this.pendingSaves.add(saving);
108
+ return saving;
109
+ }
110
+ }
@@ -20,8 +20,9 @@ import {
20
20
  isRoutable
21
21
  } from '@eclipse-glsp/client';
22
22
  import { ChannelLogger } from '@hydranium/client-theia/lib/browser';
23
- import { type Clock, SystemClock } from '@hydranium/protocol';
24
- import { inject, injectable } from '@theia/core/shared/inversify';
23
+ import { Clock } from '@hydranium/client-theia/lib/common';
24
+ import { SystemClock } from '@hydranium/protocol';
25
+ import { inject, injectable, optional } from '@theia/core/shared/inversify';
25
26
  import { type VNode } from 'snabbdom';
26
27
 
27
28
  /** How many scoped element ids the log line names before summarising the rest.
@@ -71,10 +72,8 @@ const SCOPE_ID_CAP = 3;
71
72
  export class HydraniumHiddenBoundsUpdater extends GLSPHiddenBoundsUpdater {
72
73
  @inject(ChannelLogger) protected readonly channel!: ChannelLogger;
73
74
 
74
- /** Not injected: the browser container binds no {@link Clock}, and this only
75
- * measures — no logic is gated on time, so there is nothing to fake in
76
- * production. Overridden in tests for a deterministic elapsed value. */
77
- protected readonly clock: Clock = new SystemClock();
75
+ /** The diagram container's {@link Clock}, or a `SystemClock`; it only measures. */
76
+ @inject(Clock) @optional() protected readonly clock: Clock = new SystemClock();
78
77
 
79
78
  /**
80
79
  * Scope description for the in-flight request, read from the `cause` in
@@ -17,6 +17,7 @@ export * from './diagram-widget';
17
17
  export * from './glsp-client-theia-module';
18
18
  export * from './glsp-diagram-manager';
19
19
  export * from './glsp-message-service';
20
+ export * from './glsp-saveable';
20
21
  export * from './glsp-theia-frontend-module';
21
22
  export * from './hidden-bounds-updater';
22
23
  export * from './hydranium-glsp-diagram-configuration';
@@ -8,9 +8,7 @@
8
8
  ********************************************************************************/
9
9
 
10
10
  import { GLSPContribution } from '@eclipse-glsp/theia-integration/lib/common';
11
- import { SocketConnectionForwarder } from '@eclipse-glsp/theia-integration/lib/node';
12
11
  import { AbstractSocketForwardingConnectionHandler } from '@hydranium/client-theia/lib/node';
13
- import { type Channel, type Disposable } from '@theia/core';
14
12
  import { injectable, unmanaged } from '@theia/core/shared/inversify';
15
13
  import type * as net from 'net';
16
14
 
@@ -48,15 +46,13 @@ export interface GlspServerConnectionHandlerOptions {
48
46
  /**
49
47
  * Bridges a Theia browser-frontend channel to a GLSP server's TCP socket.
50
48
  *
51
- * The port-discovery + buffer-and-replay race fix + connect orchestration live
52
- * on the cross-head {@link AbstractSocketForwardingConnectionHandler} base; this
53
- * subclass supplies only the GLSP specifics — the per-language servicePath
49
+ * The port discovery, the buffer-and-replay race fix, the connect orchestration
50
+ * and the byte forwarder live on the cross-head
51
+ * {@link AbstractSocketForwardingConnectionHandler} base; this subclass supplies
52
+ * only the GLSP specifics — the per-language servicePath
54
53
  * (`GLSPContribution.servicePath + '/' + languageContributionId`), the port
55
- * command, the log labels — and plugs in `@eclipse-glsp/theia-integration`'s
56
- * `SocketConnectionForwarder` as the byte relay. Adopters with different
57
- * language ids or command names subclass with a one-line `super({...})` call.
58
- * Sibling of `@hydranium/data-client-theia`'s `DataServerConnectionHandler`,
59
- * which subclasses the same base with its own GLSP-free forwarder.
54
+ * command, the log labels. Adopters with different language ids or command
55
+ * names subclass with a one-line `super({...})` call.
60
56
  */
61
57
  @injectable()
62
58
  export class GlspServerConnectionHandler extends AbstractSocketForwardingConnectionHandler {
@@ -72,8 +68,4 @@ export class GlspServerConnectionHandler extends AbstractSocketForwardingConnect
72
68
  onSocketCreated: options.onSocketCreated
73
69
  });
74
70
  }
75
-
76
- protected forwardToSocketConnection(clientChannel: Channel, socket: net.Socket): Disposable {
77
- return new SocketConnectionForwarder(clientChannel, socket);
78
- }
79
71
  }