@hydranium/glsp-client-theia 1.0.0-next.15 → 1.0.0-next.155

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 (42) hide show
  1. package/README.md +19 -7
  2. package/lib/browser/diagram-loader.d.ts +16 -4
  3. package/lib/browser/diagram-loader.d.ts.map +1 -1
  4. package/lib/browser/diagram-loader.js +18 -5
  5. package/lib/browser/diagram-loader.js.map +1 -1
  6. package/lib/browser/diagram-widget.d.ts +13 -1
  7. package/lib/browser/diagram-widget.d.ts.map +1 -1
  8. package/lib/browser/diagram-widget.js +19 -0
  9. package/lib/browser/diagram-widget.js.map +1 -1
  10. package/lib/browser/glsp-diagram-manager.d.ts +22 -0
  11. package/lib/browser/glsp-diagram-manager.d.ts.map +1 -1
  12. package/lib/browser/glsp-diagram-manager.js +26 -0
  13. package/lib/browser/glsp-diagram-manager.js.map +1 -1
  14. package/lib/browser/glsp-message-service.d.ts +8 -0
  15. package/lib/browser/glsp-message-service.d.ts.map +1 -1
  16. package/lib/browser/glsp-message-service.js +8 -0
  17. package/lib/browser/glsp-message-service.js.map +1 -1
  18. package/lib/browser/glsp-saveable.d.ts +66 -0
  19. package/lib/browser/glsp-saveable.d.ts.map +1 -0
  20. package/lib/browser/glsp-saveable.js +109 -0
  21. package/lib/browser/glsp-saveable.js.map +1 -0
  22. package/lib/browser/hidden-bounds-updater.d.ts +2 -4
  23. package/lib/browser/hidden-bounds-updater.d.ts.map +1 -1
  24. package/lib/browser/hidden-bounds-updater.js +7 -3
  25. package/lib/browser/hidden-bounds-updater.js.map +1 -1
  26. package/lib/browser/index.d.ts +2 -0
  27. package/lib/browser/index.d.ts.map +1 -1
  28. package/lib/browser/index.js +1 -0
  29. package/lib/browser/index.js.map +1 -1
  30. package/lib/node/glsp-server-connection-handler.d.ts +16 -10
  31. package/lib/node/glsp-server-connection-handler.d.ts.map +1 -1
  32. package/lib/node/glsp-server-connection-handler.js +9 -15
  33. package/lib/node/glsp-server-connection-handler.js.map +1 -1
  34. package/package.json +9 -5
  35. package/src/browser/diagram-loader.ts +18 -5
  36. package/src/browser/diagram-widget.ts +24 -3
  37. package/src/browser/glsp-diagram-manager.ts +29 -0
  38. package/src/browser/glsp-message-service.ts +8 -0
  39. package/src/browser/glsp-saveable.ts +110 -0
  40. package/src/browser/hidden-bounds-updater.ts +5 -6
  41. package/src/browser/index.ts +6 -0
  42. package/src/node/glsp-server-connection-handler.ts +17 -15
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
@@ -110,10 +110,22 @@ export declare class HydraniumDiagramLoader extends DiagramLoader {
110
110
  protected reportLoadFailure(err: unknown): Promise<boolean>;
111
111
  /**
112
112
  * The sentence a failed load is reported with, on every surface that reports
113
- * it, and the only seam an adopter rewords or localizes it at. Public
114
- * because the canvas overlay is one of those surfaces and lives in another
115
- * class: it renders this failure exactly when the `StatusAction` did not
116
- * land, so a second copy of the sentence there could only ever drift unseen.
113
+ * it. Public because the canvas overlay is one of those surfaces and lives in
114
+ * another class: it renders this failure exactly when the `StatusAction` did
115
+ * not land, so a second copy of the sentence there could only ever drift
116
+ * unseen.
117
+ *
118
+ * **The seam and the catalogue key answer different questions, so it carries
119
+ * both.** Overriding this method changes the WORDING for every user of one
120
+ * adopter's product; the key is what gives a reader the sentence in their own
121
+ * language, and no override can supply that without an adopter writing a
122
+ * subclass per locale — which is the thing a catalogue exists to avoid. Two
123
+ * of the three surfaces this reaches are user-visible, so the audience
124
+ * triage answers it: a host-bound string a user sees takes an inline key.
125
+ *
126
+ * The Output-channel line is therefore localized too, which is deliberate
127
+ * rather than overlooked — the alternative is a second English copy of one
128
+ * sentence, and the reason for a single source here has not changed.
117
129
  */
118
130
  loadFailureLabel(err: unknown): string;
119
131
  /** Render a thrown value as a message. Shared so the channel line, the status
@@ -1 +1 @@
1
- {"version":3,"file":"diagram-loader.d.ts","sourceRoot":"","sources":["../../src/browser/diagram-loader.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAElF,OAAO,EAAE,aAAa,EAAE,KAAK,qBAAqB,EAAgB,MAAM,sBAAsB,CAAC;AAC/F,OAAO,EAAE,aAAa,EAAE,MAAM,qCAAqC,CAAC;AACpE,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAG/C;;;;;;GAMG;AACH,MAAM,MAAM,kBAAkB,GAAG,kBAAkB,GAAG,kBAAkB,CAAC;AAEzE,MAAM,WAAW,kBAAkB;IAChC,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC;CAC5B;AAED,MAAM,WAAW,kBAAkB;IAChC,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC;IAC1B,iFAAiF;IACjF,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB;;;;;;;;;;;OAWG;IACH,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;CAC7B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,qBACa,sBAAuB,SAAQ,aAAa;IAC/B,SAAS,CAAC,QAAQ,CAAC,OAAO,EAAG,aAAa,CAAC;IAElE,SAAS,CAAC,QAAQ,CAAC,OAAO,+BAAsC;IAChE,SAAS,CAAC,OAAO,CAAC,EAAE,kBAAkB,CAAC;IAEvC;;;+DAG2D;IAC3D,IAAI,WAAW,IAAI,kBAAkB,GAAG,SAAS,CAEhD;IAED;uEACmE;IACnE,eAAe,IAAI,OAAO,CAAC,kBAAkB,CAAC;IAI/B,IAAI,CAAC,OAAO,CAAC,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC;IAcnE;;;;;;;;;;;OAWG;IACH,SAAS,CAAC,MAAM,CAAC,OAAO,EAAE,kBAAkB,GAAG,IAAI;IAQnD;;;;;;;;;;;OAWG;cACa,iBAAiB,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IAYjE;;;;;;OAMG;IACH,gBAAgB,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM;IAItC;qFACiF;IACjF,SAAS,CAAC,WAAW,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM;CAG7C"}
1
+ {"version":3,"file":"diagram-loader.d.ts","sourceRoot":"","sources":["../../src/browser/diagram-loader.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAElF,OAAO,EAAE,aAAa,EAAE,KAAK,qBAAqB,EAAgB,MAAM,sBAAsB,CAAC;AAC/F,OAAO,EAAE,aAAa,EAAE,MAAM,qCAAqC,CAAC;AACpE,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAI/C;;;;;;GAMG;AACH,MAAM,MAAM,kBAAkB,GAAG,kBAAkB,GAAG,kBAAkB,CAAC;AAEzE,MAAM,WAAW,kBAAkB;IAChC,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC;CAC5B;AAED,MAAM,WAAW,kBAAkB;IAChC,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC;IAC1B,iFAAiF;IACjF,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB;;;;;;;;;;;OAWG;IACH,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;CAC7B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,qBACa,sBAAuB,SAAQ,aAAa;IAC/B,SAAS,CAAC,QAAQ,CAAC,OAAO,EAAG,aAAa,CAAC;IAElE,SAAS,CAAC,QAAQ,CAAC,OAAO,+BAAsC;IAChE,SAAS,CAAC,OAAO,CAAC,EAAE,kBAAkB,CAAC;IAEvC;;;+DAG2D;IAC3D,IAAI,WAAW,IAAI,kBAAkB,GAAG,SAAS,CAEhD;IAED;uEACmE;IACnE,eAAe,IAAI,OAAO,CAAC,kBAAkB,CAAC;IAI/B,IAAI,CAAC,OAAO,CAAC,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC;IAcnE;;;;;;;;;;;OAWG;IACH,SAAS,CAAC,MAAM,CAAC,OAAO,EAAE,kBAAkB,GAAG,IAAI;IAQnD;;;;;;;;;;;OAWG;cACa,iBAAiB,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IAYjE;;;;;;;;;;;;;;;;;;OAkBG;IACH,gBAAgB,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM;IAItC;qFACiF;IACjF,SAAS,CAAC,WAAW,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM;CAG7C"}
@@ -21,6 +21,7 @@ exports.HydraniumDiagramLoader = void 0;
21
21
  const client_1 = require("@eclipse-glsp/client");
22
22
  const browser_1 = require("@hydranium/client-theia/lib/browser");
23
23
  const protocol_1 = require("@hydranium/protocol");
24
+ const core_1 = require("@theia/core");
24
25
  const inversify_1 = require("@theia/core/shared/inversify");
25
26
  /**
26
27
  * Diagram loader that never lets a load failure vanish.
@@ -128,13 +129,25 @@ let HydraniumDiagramLoader = class HydraniumDiagramLoader extends client_1.Diagr
128
129
  }
129
130
  /**
130
131
  * The sentence a failed load is reported with, on every surface that reports
131
- * it, and the only seam an adopter rewords or localizes it at. Public
132
- * because the canvas overlay is one of those surfaces and lives in another
133
- * class: it renders this failure exactly when the `StatusAction` did not
134
- * land, so a second copy of the sentence there could only ever drift unseen.
132
+ * it. Public because the canvas overlay is one of those surfaces and lives in
133
+ * another class: it renders this failure exactly when the `StatusAction` did
134
+ * not land, so a second copy of the sentence there could only ever drift
135
+ * unseen.
136
+ *
137
+ * **The seam and the catalogue key answer different questions, so it carries
138
+ * both.** Overriding this method changes the WORDING for every user of one
139
+ * adopter's product; the key is what gives a reader the sentence in their own
140
+ * language, and no override can supply that without an adopter writing a
141
+ * subclass per locale — which is the thing a catalogue exists to avoid. Two
142
+ * of the three surfaces this reaches are user-visible, so the audience
143
+ * triage answers it: a host-bound string a user sees takes an inline key.
144
+ *
145
+ * The Output-channel line is therefore localized too, which is deliberate
146
+ * rather than overlooked — the alternative is a second English copy of one
147
+ * sentence, and the reason for a single source here has not changed.
135
148
  */
136
149
  loadFailureLabel(err) {
137
- return `Diagram failed to load: ${this.formatError(err)}`;
150
+ return core_1.nls.localize('hydranium/glsp-client-theia/diagram-load-failed', 'Diagram failed to load: {0}', this.formatError(err));
138
151
  }
139
152
  /** Render a thrown value as a message. Shared so the channel line, the status
140
153
  * overlay and any consumer rendering {@link DiagramLoadFailure.error} agree. */
@@ -1 +1 @@
1
- {"version":3,"file":"diagram-loader.js","sourceRoot":"","sources":["../../src/browser/diagram-loader.ts"],"names":[],"mappings":";AAAA;;;;;;;kFAOkF;;;;;;;;;;;;AAElF,iDAA+F;AAC/F,iEAAoE;AACpE,kDAA+C;AAC/C,4DAAkE;AAkClE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAEI,IAAM,sBAAsB,GAA5B,MAAM,sBAAuB,SAAQ,sBAAa;IACZ,OAAO,CAAiB;IAE/C,OAAO,GAAG,IAAI,mBAAQ,EAAsB,CAAC;IACtD,OAAO,CAAsB;IAEvC;;;+DAG2D;IAC3D,IAAI,WAAW;QACZ,OAAO,IAAI,CAAC,OAAO,CAAC;IACvB,CAAC;IAED;uEACmE;IACnE,eAAe;QACZ,OAAO,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC;IAC/B,CAAC;IAEQ,KAAK,CAAC,IAAI,CAAC,OAA+B;QAChD,IAAI,CAAC;YACF,MAAM,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YAC1B,IAAI,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC;QACrC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACZ,sEAAsE;YACtE,mEAAmE;YACnE,sEAAsE;YACtE,2CAA2C;YAC3C,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAC;YACnD,IAAI,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC,CAAC;QAC3D,CAAC;IACJ,CAAC;IAED;;;;;;;;;;;OAWG;IACO,MAAM,CAAC,OAA2B;QACzC,IAAI,IAAI,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;YAC9B,OAAO;QACV,CAAC;QACD,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IACjC,CAAC;IAED;;;;;;;;;;;OAWG;IACO,KAAK,CAAC,iBAAiB,CAAC,GAAY;QAC3C,MAAM,KAAK,GAAG,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC;QACzC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QAC/B,IAAI,CAAC;YACF,MAAM,IAAI,CAAC,gBAAgB,CAAC,QAAQ,CAAC,qBAAY,CAAC,MAAM,CAAC,KAAK,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC;YACxF,OAAO,IAAI,CAAC;QACf,CAAC;QAAC,OAAO,SAAS,EAAE,CAAC;YAClB,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,kEAAkE,EAAE,SAAS,CAAC,CAAC;YAClG,OAAO,KAAK,CAAC;QAChB,CAAC;IACJ,CAAC;IAED;;;;;;OAMG;IACH,gBAAgB,CAAC,GAAY;QAC1B,OAAO,2BAA2B,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC;IAC7D,CAAC;IAED;qFACiF;IACvE,WAAW,CAAC,GAAY;QAC/B,OAAO,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAC3D,CAAC;CACH,CAAA;AA9FY,wDAAsB;AACU;IAAzC,IAAA,kBAAM,EAAC,uBAAa,CAAC;8BAA8B,uBAAa;uDAAC;iCADxD,sBAAsB;IADlC,IAAA,sBAAU,GAAE;GACA,sBAAsB,CA8FlC"}
1
+ {"version":3,"file":"diagram-loader.js","sourceRoot":"","sources":["../../src/browser/diagram-loader.ts"],"names":[],"mappings":";AAAA;;;;;;;kFAOkF;;;;;;;;;;;;AAElF,iDAA+F;AAC/F,iEAAoE;AACpE,kDAA+C;AAC/C,sCAAkC;AAClC,4DAAkE;AAkClE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAEI,IAAM,sBAAsB,GAA5B,MAAM,sBAAuB,SAAQ,sBAAa;IACZ,OAAO,CAAiB;IAE/C,OAAO,GAAG,IAAI,mBAAQ,EAAsB,CAAC;IACtD,OAAO,CAAsB;IAEvC;;;+DAG2D;IAC3D,IAAI,WAAW;QACZ,OAAO,IAAI,CAAC,OAAO,CAAC;IACvB,CAAC;IAED;uEACmE;IACnE,eAAe;QACZ,OAAO,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC;IAC/B,CAAC;IAEQ,KAAK,CAAC,IAAI,CAAC,OAA+B;QAChD,IAAI,CAAC;YACF,MAAM,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YAC1B,IAAI,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC;QACrC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACZ,sEAAsE;YACtE,mEAAmE;YACnE,sEAAsE;YACtE,2CAA2C;YAC3C,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAC;YACnD,IAAI,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC,CAAC;QAC3D,CAAC;IACJ,CAAC;IAED;;;;;;;;;;;OAWG;IACO,MAAM,CAAC,OAA2B;QACzC,IAAI,IAAI,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;YAC9B,OAAO;QACV,CAAC;QACD,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IACjC,CAAC;IAED;;;;;;;;;;;OAWG;IACO,KAAK,CAAC,iBAAiB,CAAC,GAAY;QAC3C,MAAM,KAAK,GAAG,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC;QACzC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QAC/B,IAAI,CAAC;YACF,MAAM,IAAI,CAAC,gBAAgB,CAAC,QAAQ,CAAC,qBAAY,CAAC,MAAM,CAAC,KAAK,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC;YACxF,OAAO,IAAI,CAAC;QACf,CAAC;QAAC,OAAO,SAAS,EAAE,CAAC;YAClB,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,kEAAkE,EAAE,SAAS,CAAC,CAAC;YAClG,OAAO,KAAK,CAAC;QAChB,CAAC;IACJ,CAAC;IAED;;;;;;;;;;;;;;;;;;OAkBG;IACH,gBAAgB,CAAC,GAAY;QAC1B,OAAO,UAAG,CAAC,QAAQ,CAAC,iDAAiD,EAAE,6BAA6B,EAAE,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC;IAChI,CAAC;IAED;qFACiF;IACvE,WAAW,CAAC,GAAY;QAC/B,OAAO,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAC3D,CAAC;CACH,CAAA;AA1GY,wDAAsB;AACU;IAAzC,IAAA,kBAAM,EAAC,uBAAa,CAAC;8BAA8B,uBAAa;uDAAC;iCADxD,sBAAsB;IADlC,IAAA,sBAAU,GAAE;GACA,sBAAsB,CA0GlC"}
@@ -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":";AAAA;;;;;;;kFAOkF;;;;;;;;;AAElF,iDAA2E;AAC3E,uEAAmG;AAInG,4DAA0E;AAC1E,qDAAmF;AACnF,mDAAwD;AACxD,yEAAyE;AACzE,gFAAgF;AAChF,yEAAyE;AACzE,2CAAyC;AAEzC,8EAA8E;AACjE,QAAA,qBAAqB,GAAG,2BAA2B,CAAC;AAEjE;kFACkF;AACrE,QAAA,4BAA4B,GAAG,GAAG,6BAAqB,SAAS,CAAC;AAE9E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAEI,IAAM,0BAA0B,GAAhC,MAAM,0BAA2B,SAAQ,qCAAiB;IACpD,cAAc,CAAe;IAEvC;;;;OAIG;IACM,SAAS,CAAC,OAAiC,EAAE,WAAsB;QACzE,KAAK,CAAC,SAAS,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;QACtC,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC;QACxB,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,cAAc,EAAE,CAAC;QACtC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACtC,CAAC;IAED,kFAAkF;IACxE,cAAc;QACrB,OAAO,IAAI,qCAAqB,CAAC,IAAI,CAAC,gBAAgB,EAAE,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,6BAAoB,CAAC,CAAC,CAAC;IACvG,CAAC;IAEkB,aAAa,CAAC,GAAY;QAC1C,yEAAyE;QACzE,oDAAoD;QACpD,IAAI,CAAC,kBAAkB,EAAE,CAAC;QAC1B,KAAK,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC;IAC5B,CAAC;IAEQ,OAAO;QACb,IAAI,CAAC,kBAAkB,EAAE,CAAC;QAC1B,KAAK,CAAC,OAAO,EAAE,CAAC;IACnB,CAAC;IAED;;;;;;;OAOG;IACO,kBAAkB;QACzB,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;YACvB,OAAO;QACV,CAAC;QACD,MAAM,MAAM,GAAG,IAAI,CAAC,sBAAsB,CAAC;QAC3C,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,WAAW,KAAK,SAAS,EAAE,CAAC;YAC/C,OAAO;QACV,CAAC;QACD,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,oBAAoB,EAAE,CAAC;QAClD,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QAC3C,4EAA4E;QAC5E,2EAA2E;QAC3E,uDAAuD;QACvD,MAAM,CAAC,eAAe,EAAE,CAAC,IAAI,CAC1B,OAAO,CAAC,EAAE,CAAC,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,EACtC,GAAG,EAAE,CAAC,IAAI,CAAC,kBAAkB,EAAE,CACjC,CAAC;IACL,CAAC;IAED;;;;;;OAMG;IACO,aAAa,CAAC,OAA2B;QAChD,IAAI,OAAO,CAAC,MAAM,KAAK,QAAQ,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC;YACpD,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;YACpC,OAAO;QACV,CAAC;QACD,IAAI,CAAC,kBAAkB,EAAE,CAAC;IAC7B,CAAC;IAED;;;;;;;;;OASG;IACO,eAAe,CAAC,KAAc;QACrC,MAAM,OAAO,GAAG,IAAI,CAAC,cAAc,CAAC;QACpC,MAAM,MAAM,GAAG,IAAI,CAAC,sBAAsB,CAAC;QAC3C,IAAI,CAAC,OAAO,IAAI,CAAC,MAAM,EAAE,CAAC;YACvB,OAAO;QACV,CAAC;QACD,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC,oCAA4B,CAAC,CAAC;QACpD,MAAM,KAAK,GAAG,OAAO,CAAC,aAAa,CAAC,IAAI,6BAAqB,QAAQ,CAAC,CAAC;QACvE,IAAI,KAAK,EAAE,CAAC;YACT,KAAK,CAAC,WAAW,GAAG,MAAM,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC;QACtD,CAAC;IACJ,CAAC;IAES,kBAAkB;QACzB,IAAI,CAAC,cAAc,EAAE,MAAM,EAAE,CAAC;QAC9B,IAAI,CAAC,cAAc,GAAG,SAAS,CAAC;IACnC,CAAC;IAED;;oFAEgF;IACtE,oBAAoB;QAC3B,MAAM,OAAO,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QAC9C,OAAO,CAAC,SAAS,GAAG,6BAAqB,CAAC;QAC1C,MAAM,OAAO,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QAC9C,OAAO,CAAC,SAAS,GAAG,GAAG,6BAAqB,UAAU,CAAC;QACvD,MAAM,KAAK,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QAC5C,KAAK,CAAC,SAAS,GAAG,GAAG,6BAAqB,QAAQ,CAAC;QACnD,KAAK,CAAC,WAAW,GAAG,IAAI,CAAC,YAAY,CAAC;QACtC,OAAO,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;QAC7B,OAAO,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QAC3B,OAAO,OAAO,CAAC;IAClB,CAAC;IAED;sEACkE;IAClE,IAAc,YAAY;QACvB,OAAO,oBAAoB,CAAC;IAC/B,CAAC;IAED;;;;;OAKG;IACH,IAAc,sBAAsB;QACjC,MAAM,MAAM,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAgB,sBAAa,CAAC,CAAC;QAClE,OAAO,MAAM,YAAY,uCAAsB,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC;IACxE,CAAC;CACH,CAAA;AAtIY,gEAA0B;qCAA1B,0BAA0B;IADtC,IAAA,sBAAU,GAAE;GACA,0BAA0B,CAsItC"}
@@ -8,6 +8,8 @@
8
8
  ********************************************************************************/
9
9
  import { GLSPDiagramManager } from '@eclipse-glsp/theia-integration';
10
10
  import { type GLSPDiagramLanguage } from '@eclipse-glsp/theia-integration/lib/common';
11
+ import { type GLSPDiagramWidget } from '@eclipse-glsp/theia-integration/lib/browser';
12
+ import { type WidgetOpenerOptions } from '@theia/core/lib/browser';
11
13
  /**
12
14
  * `GLSPDiagramManager` subclass that derives the language-correlated getters
13
15
  * (`fileExtensions`, `diagramType`, `contributionId`, `iconClass`) from a
@@ -42,5 +44,25 @@ export declare abstract class AbstractHydraniumGlspDiagramManager extends GLSPDi
42
44
  get contributionId(): string;
43
45
  get iconClass(): string;
44
46
  get label(): string;
47
+ /**
48
+ * Drops a `selection` key that is present but `undefined` before the base
49
+ * class reads it.
50
+ *
51
+ * Without this, opening a diagram from Theia's file picker throws and the
52
+ * editor never leaves "Loading diagram…". Upstream's
53
+ * `OptionsWithSelection.is` tests `'selection' in options`, which is true for
54
+ * a key explicitly set to `undefined`, and the branch it guards then calls
55
+ * `Object.keys` on that value. Theia's own `QuickFileOpenService` always sets
56
+ * the key — its `buildOpenerOptions` returns `{ selection: range }`, and
57
+ * `range` is `undefined` unless the query carried a `:line:column` suffix —
58
+ * so the crash is reached by the ordinary act of opening a diagram by name.
59
+ *
60
+ * Normalising the OPTIONS rather than rebinding
61
+ * `TheiaOpenerOptionsNavigationService`: the service is shared by every
62
+ * diagram type in the container, so replacing it would make one adopter's
63
+ * fix silently global, and the guard belongs where the value enters rather
64
+ * than where it is consumed. The base method stays the single implementation.
65
+ */
66
+ protected handleNavigations(widget: GLSPDiagramWidget, options?: WidgetOpenerOptions): boolean;
45
67
  }
46
68
  //# sourceMappingURL=glsp-diagram-manager.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"glsp-diagram-manager.d.ts","sourceRoot":"","sources":["../../src/browser/glsp-diagram-manager.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAGlF,OAAO,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAC;AACrE,OAAO,EAAE,KAAK,mBAAmB,EAAE,MAAM,4CAA4C,CAAC;AAGtF;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,8BACsB,mCAAoC,SAAQ,kBAAkB;IACjF,8EAA8E;IAC9E,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC,eAAe,EAAE,mBAAmB,CAAC;IAEjE,wEAAwE;IACxE,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAEjD,sFAAsF;IACtF,SAAS,CAAC,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAE5C,IAAa,cAAc,IAAI,MAAM,EAAE,CAEtC;IAED,IAAa,WAAW,IAAI,MAAM,CAEjC;IAED,IAAa,cAAc,IAAI,MAAM,CAEpC;IAED,IAAa,SAAS,IAAI,MAAM,CAE/B;IAED,IAAI,KAAK,IAAI,MAAM,CAElB;CACH"}
1
+ {"version":3,"file":"glsp-diagram-manager.d.ts","sourceRoot":"","sources":["../../src/browser/glsp-diagram-manager.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAGlF,OAAO,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAC;AACrE,OAAO,EAAE,KAAK,mBAAmB,EAAE,MAAM,4CAA4C,CAAC;AACtF,OAAO,EAAE,KAAK,iBAAiB,EAAE,MAAM,6CAA6C,CAAC;AACrF,OAAO,EAAE,KAAK,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAGnE;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,8BACsB,mCAAoC,SAAQ,kBAAkB;IACjF,8EAA8E;IAC9E,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC,eAAe,EAAE,mBAAmB,CAAC;IAEjE,wEAAwE;IACxE,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAEjD,sFAAsF;IACtF,SAAS,CAAC,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAE5C,IAAa,cAAc,IAAI,MAAM,EAAE,CAEtC;IAED,IAAa,WAAW,IAAI,MAAM,CAEjC;IAED,IAAa,cAAc,IAAI,MAAM,CAEpC;IAED,IAAa,SAAS,IAAI,MAAM,CAE/B;IAED,IAAI,KAAK,IAAI,MAAM,CAElB;IAED;;;;;;;;;;;;;;;;;;OAkBG;cACgB,iBAAiB,CAAC,MAAM,EAAE,iBAAiB,EAAE,OAAO,CAAC,EAAE,mBAAmB,GAAG,OAAO;CAOzG"}
@@ -58,6 +58,32 @@ let AbstractHydraniumGlspDiagramManager = class AbstractHydraniumGlspDiagramMana
58
58
  get label() {
59
59
  return this.managerLabel;
60
60
  }
61
+ /**
62
+ * Drops a `selection` key that is present but `undefined` before the base
63
+ * class reads it.
64
+ *
65
+ * Without this, opening a diagram from Theia's file picker throws and the
66
+ * editor never leaves "Loading diagram…". Upstream's
67
+ * `OptionsWithSelection.is` tests `'selection' in options`, which is true for
68
+ * a key explicitly set to `undefined`, and the branch it guards then calls
69
+ * `Object.keys` on that value. Theia's own `QuickFileOpenService` always sets
70
+ * the key — its `buildOpenerOptions` returns `{ selection: range }`, and
71
+ * `range` is `undefined` unless the query carried a `:line:column` suffix —
72
+ * so the crash is reached by the ordinary act of opening a diagram by name.
73
+ *
74
+ * Normalising the OPTIONS rather than rebinding
75
+ * `TheiaOpenerOptionsNavigationService`: the service is shared by every
76
+ * diagram type in the container, so replacing it would make one adopter's
77
+ * fix silently global, and the guard belongs where the value enters rather
78
+ * than where it is consumed. The base method stays the single implementation.
79
+ */
80
+ handleNavigations(widget, options) {
81
+ if (options && 'selection' in options && options.selection === undefined) {
82
+ const { selection: _dropped, ...rest } = options;
83
+ return super.handleNavigations(widget, rest);
84
+ }
85
+ return super.handleNavigations(widget, options);
86
+ }
61
87
  };
62
88
  exports.AbstractHydraniumGlspDiagramManager = AbstractHydraniumGlspDiagramManager;
63
89
  exports.AbstractHydraniumGlspDiagramManager = AbstractHydraniumGlspDiagramManager = __decorate([
@@ -1 +1 @@
1
- {"version":3,"file":"glsp-diagram-manager.js","sourceRoot":"","sources":["../../src/browser/glsp-diagram-manager.ts"],"names":[],"mappings":";AAAA;;;;;;;kFAOkF;;;;;;;;;AAElF,iDAAwD;AACxD,uEAAqE;AAErE,4DAA0D;AAE1D;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEI,IAAe,mCAAmC,GAAlD,MAAe,mCAAoC,SAAQ,sCAAkB;IAOjF,sFAAsF;IACnE,eAAe,CAAU;IAE5C,IAAa,cAAc;QACxB,OAAO,CAAC,GAAG,IAAI,CAAC,eAAe,CAAC,cAAc,CAAC,CAAC;IACnD,CAAC;IAED,IAAa,WAAW;QACrB,OAAO,IAAI,CAAC,eAAe,CAAC,WAAW,CAAC;IAC3C,CAAC;IAED,IAAa,cAAc;QACxB,OAAO,IAAI,CAAC,eAAe,CAAC,cAAc,CAAC;IAC9C,CAAC;IAED,IAAa,SAAS;QACnB,OAAO,IAAI,CAAC,eAAe,IAAI,IAAI,CAAC,eAAe,CAAC,SAAS,IAAI,IAAA,yBAAgB,EAAC,oBAAoB,CAAC,CAAC;IAC3G,CAAC;IAED,IAAI,KAAK;QACN,OAAO,IAAI,CAAC,YAAY,CAAC;IAC5B,CAAC;CACH,CAAA;AA7BqB,kFAAmC;8CAAnC,mCAAmC;IADxD,IAAA,sBAAU,GAAE;GACS,mCAAmC,CA6BxD"}
1
+ {"version":3,"file":"glsp-diagram-manager.js","sourceRoot":"","sources":["../../src/browser/glsp-diagram-manager.ts"],"names":[],"mappings":";AAAA;;;;;;;kFAOkF;;;;;;;;;AAElF,iDAAwD;AACxD,uEAAqE;AAIrE,4DAA0D;AAE1D;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEI,IAAe,mCAAmC,GAAlD,MAAe,mCAAoC,SAAQ,sCAAkB;IAOjF,sFAAsF;IACnE,eAAe,CAAU;IAE5C,IAAa,cAAc;QACxB,OAAO,CAAC,GAAG,IAAI,CAAC,eAAe,CAAC,cAAc,CAAC,CAAC;IACnD,CAAC;IAED,IAAa,WAAW;QACrB,OAAO,IAAI,CAAC,eAAe,CAAC,WAAW,CAAC;IAC3C,CAAC;IAED,IAAa,cAAc;QACxB,OAAO,IAAI,CAAC,eAAe,CAAC,cAAc,CAAC;IAC9C,CAAC;IAED,IAAa,SAAS;QACnB,OAAO,IAAI,CAAC,eAAe,IAAI,IAAI,CAAC,eAAe,CAAC,SAAS,IAAI,IAAA,yBAAgB,EAAC,oBAAoB,CAAC,CAAC;IAC3G,CAAC;IAED,IAAI,KAAK;QACN,OAAO,IAAI,CAAC,YAAY,CAAC;IAC5B,CAAC;IAED;;;;;;;;;;;;;;;;;;OAkBG;IACgB,iBAAiB,CAAC,MAAyB,EAAE,OAA6B;QAC1F,IAAI,OAAO,IAAI,WAAW,IAAI,OAAO,IAAK,OAAmC,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;YACrG,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,IAAI,EAAE,GAAG,OAAwD,CAAC;YAClG,OAAO,KAAK,CAAC,iBAAiB,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QAChD,CAAC;QACD,OAAO,KAAK,CAAC,iBAAiB,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnD,CAAC;CACH,CAAA;AAxDqB,kFAAmC;8CAAnC,mCAAmC;IADxD,IAAA,sBAAU,GAAE;GACS,mCAAmC,CAwDxD"}
@@ -22,6 +22,14 @@ import { type interfaces } from '@theia/core/shared/inversify';
22
22
  * Matching an English literal fails silently — no error, no log line, just the
23
23
  * duplicate progress popup back — so this needs keeping in step with
24
24
  * `RequestModelActionHandler` on every GLSP bump.
25
+ *
26
+ * **Exported to be imported, and it must NOT be externalized.** An adopter
27
+ * subclassing the message service needs the same literal to match on, and a
28
+ * second copy of it is a second thing to keep in step across that bump. It is
29
+ * also the one user-visible string in the framework that is deliberately excluded
30
+ * from the message catalogue: it exists to equal an upstream English literal that
31
+ * lives in no catalogue, so giving it a code and a translation would break the
32
+ * match it exists for.
25
33
  */
26
34
  export declare const MODEL_LOADING_PROGRESS_TITLE = "Model loading in progress";
27
35
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"glsp-message-service.d.ts","sourceRoot":"","sources":["../../src/browser/glsp-message-service.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAElF,OAAO,EAAE,KAAK,iBAAiB,EAAE,KAAK,mBAAmB,EAAE,KAAK,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AACnH,OAAO,EAAE,uBAAuB,EAAE,MAAM,iCAAiC,CAAC;AAC1E,OAAO,EAAE,KAAK,UAAU,EAAc,MAAM,8BAA8B,CAAC;AAE3E;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,4BAA4B,8BAA8B,CAAC;AAExE;;;;;;;;;;;;GAYG;AACH,qBACa,2BAA4B,SAAQ,uBAAuB;IACrE;;mBAEe;IACf,SAAS,CAAC,qBAAqB,cAAqB;cAEjC,aAAa,CAAC,MAAM,EAAE,mBAAmB,GAAG,IAAI;cAQhD,cAAc,CAAC,MAAM,EAAE,oBAAoB,GAAG,IAAI;cAOlD,WAAW,CAAC,MAAM,EAAE,iBAAiB,GAAG,IAAI;CAQjE;AAED;;;;;;;;GAQG;AACH,wBAAgB,+BAA+B,CAAC,IAAI,EAAE,UAAU,CAAC,IAAI,EAAE,OAAO,EAAE,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,CAAC,MAAM,GAAG,IAAI,CAMnI"}
1
+ {"version":3,"file":"glsp-message-service.d.ts","sourceRoot":"","sources":["../../src/browser/glsp-message-service.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAElF,OAAO,EAAE,KAAK,iBAAiB,EAAE,KAAK,mBAAmB,EAAE,KAAK,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AACnH,OAAO,EAAE,uBAAuB,EAAE,MAAM,iCAAiC,CAAC;AAC1E,OAAO,EAAE,KAAK,UAAU,EAAc,MAAM,8BAA8B,CAAC;AAE3E;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,eAAO,MAAM,4BAA4B,8BAA8B,CAAC;AAExE;;;;;;;;;;;;GAYG;AACH,qBACa,2BAA4B,SAAQ,uBAAuB;IACrE;;mBAEe;IACf,SAAS,CAAC,qBAAqB,cAAqB;cAEjC,aAAa,CAAC,MAAM,EAAE,mBAAmB,GAAG,IAAI;cAQhD,cAAc,CAAC,MAAM,EAAE,oBAAoB,GAAG,IAAI;cAOlD,WAAW,CAAC,MAAM,EAAE,iBAAiB,GAAG,IAAI;CAQjE;AAED;;;;;;;;GAQG;AACH,wBAAgB,+BAA+B,CAAC,IAAI,EAAE,UAAU,CAAC,IAAI,EAAE,OAAO,EAAE,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,CAAC,MAAM,GAAG,IAAI,CAMnI"}
@@ -31,6 +31,14 @@ const inversify_1 = require("@theia/core/shared/inversify");
31
31
  * Matching an English literal fails silently — no error, no log line, just the
32
32
  * duplicate progress popup back — so this needs keeping in step with
33
33
  * `RequestModelActionHandler` on every GLSP bump.
34
+ *
35
+ * **Exported to be imported, and it must NOT be externalized.** An adopter
36
+ * subclassing the message service needs the same literal to match on, and a
37
+ * second copy of it is a second thing to keep in step across that bump. It is
38
+ * also the one user-visible string in the framework that is deliberately excluded
39
+ * from the message catalogue: it exists to equal an upstream English literal that
40
+ * lives in no catalogue, so giving it a code and a translation would break the
41
+ * match it exists for.
34
42
  */
35
43
  exports.MODEL_LOADING_PROGRESS_TITLE = 'Model loading in progress';
36
44
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"glsp-message-service.js","sourceRoot":"","sources":["../../src/browser/glsp-message-service.ts"],"names":[],"mappings":";AAAA;;;;;;;kFAOkF;;;;;;;;;AA4ElF,0EAMC;AA/ED,uEAA0E;AAC1E,4DAA2E;AAE3E;;;;;;;;;;;;;GAaG;AACU,QAAA,4BAA4B,GAAG,2BAA2B,CAAC;AAExE;;;;;;;;;;;;GAYG;AAEI,IAAM,2BAA2B,GAAjC,MAAM,2BAA4B,SAAQ,2CAAuB;IACrE;;mBAEe;IACL,qBAAqB,GAAG,IAAI,GAAG,EAAU,CAAC;IAEjC,aAAa,CAAC,MAA2B;QACzD,IAAI,MAAM,CAAC,KAAK,KAAK,oCAA4B,EAAE,CAAC;YACjD,IAAI,CAAC,qBAAqB,CAAC,GAAG,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;YAClD,OAAO;QACV,CAAC;QACD,KAAK,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;IAC/B,CAAC;IAEkB,cAAc,CAAC,MAA4B;QAC3D,IAAI,IAAI,CAAC,qBAAqB,CAAC,GAAG,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE,CAAC;YACrD,OAAO;QACV,CAAC;QACD,KAAK,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;IAChC,CAAC;IAEkB,WAAW,CAAC,MAAyB;QACrD,4EAA4E;QAC5E,mDAAmD;QACnD,IAAI,IAAI,CAAC,qBAAqB,CAAC,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE,CAAC;YACxD,OAAO;QACV,CAAC;QACD,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;IAC7B,CAAC;CACH,CAAA;AA7BY,kEAA2B;sCAA3B,2BAA2B;IADvC,IAAA,sBAAU,GAAE;GACA,2BAA2B,CA6BvC;AAED;;;;;;;;GAQG;AACH,SAAgB,+BAA+B,CAAC,IAAqB,EAAE,OAA2B,EAAE,MAAyB;IAC1H,IAAI,OAAO,CAAC,2CAAuB,CAAC,EAAE,CAAC;QACpC,MAAM,CAAC,2CAAuB,CAAC,CAAC,EAAE,CAAC,2BAA2B,CAAC,CAAC,gBAAgB,EAAE,CAAC;IACtF,CAAC;SAAM,CAAC;QACL,IAAI,CAAC,2CAAuB,CAAC,CAAC,EAAE,CAAC,2BAA2B,CAAC,CAAC,gBAAgB,EAAE,CAAC;IACpF,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"glsp-message-service.js","sourceRoot":"","sources":["../../src/browser/glsp-message-service.ts"],"names":[],"mappings":";AAAA;;;;;;;kFAOkF;;;;;;;;;AAoFlF,0EAMC;AAvFD,uEAA0E;AAC1E,4DAA2E;AAE3E;;;;;;;;;;;;;;;;;;;;;GAqBG;AACU,QAAA,4BAA4B,GAAG,2BAA2B,CAAC;AAExE;;;;;;;;;;;;GAYG;AAEI,IAAM,2BAA2B,GAAjC,MAAM,2BAA4B,SAAQ,2CAAuB;IACrE;;mBAEe;IACL,qBAAqB,GAAG,IAAI,GAAG,EAAU,CAAC;IAEjC,aAAa,CAAC,MAA2B;QACzD,IAAI,MAAM,CAAC,KAAK,KAAK,oCAA4B,EAAE,CAAC;YACjD,IAAI,CAAC,qBAAqB,CAAC,GAAG,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;YAClD,OAAO;QACV,CAAC;QACD,KAAK,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;IAC/B,CAAC;IAEkB,cAAc,CAAC,MAA4B;QAC3D,IAAI,IAAI,CAAC,qBAAqB,CAAC,GAAG,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE,CAAC;YACrD,OAAO;QACV,CAAC;QACD,KAAK,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;IAChC,CAAC;IAEkB,WAAW,CAAC,MAAyB;QACrD,4EAA4E;QAC5E,mDAAmD;QACnD,IAAI,IAAI,CAAC,qBAAqB,CAAC,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE,CAAC;YACxD,OAAO;QACV,CAAC;QACD,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;IAC7B,CAAC;CACH,CAAA;AA7BY,kEAA2B;sCAA3B,2BAA2B;IADvC,IAAA,sBAAU,GAAE;GACA,2BAA2B,CA6BvC;AAED;;;;;;;;GAQG;AACH,SAAgB,+BAA+B,CAAC,IAAqB,EAAE,OAA2B,EAAE,MAAyB;IAC1H,IAAI,OAAO,CAAC,2CAAuB,CAAC,EAAE,CAAC;QACpC,MAAM,CAAC,2CAAuB,CAAC,CAAC,EAAE,CAAC,2BAA2B,CAAC,CAAC,gBAAgB,EAAE,CAAC;IACtF,CAAC;SAAM,CAAC;QACL,IAAI,CAAC,2CAAuB,CAAC,CAAC,EAAE,CAAC,2BAA2B,CAAC,CAAC,gBAAgB,EAAE,CAAC;IACpF,CAAC;AACJ,CAAC"}
@@ -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);