@hydranium/glsp-server 1.0.0-next.31 → 1.0.0-next.315

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 (217) hide show
  1. package/README.md +80 -88
  2. package/lib/browser/start-glsp-server-in-worker.d.ts +43 -42
  3. package/lib/browser/start-glsp-server-in-worker.d.ts.map +1 -1
  4. package/lib/browser/start-glsp-server-in-worker.js +62 -13
  5. package/lib/browser/start-glsp-server-in-worker.js.map +1 -1
  6. package/lib/command/diagram-edit-dropped-error.d.ts +31 -0
  7. package/lib/command/diagram-edit-dropped-error.d.ts.map +1 -0
  8. package/lib/command/diagram-edit-dropped-error.js +48 -0
  9. package/lib/command/diagram-edit-dropped-error.js.map +1 -0
  10. package/lib/command/hydranium-glsp-command-stack.d.ts +33 -0
  11. package/lib/command/hydranium-glsp-command-stack.d.ts.map +1 -0
  12. package/lib/command/hydranium-glsp-command-stack.js +63 -0
  13. package/lib/command/hydranium-glsp-command-stack.js.map +1 -0
  14. package/lib/command/hydranium-glsp-operation-action-handler.d.ts +64 -0
  15. package/lib/command/hydranium-glsp-operation-action-handler.d.ts.map +1 -0
  16. package/lib/command/hydranium-glsp-operation-action-handler.js +142 -0
  17. package/lib/command/hydranium-glsp-operation-action-handler.js.map +1 -0
  18. package/lib/command/hydranium-glsp-operation-command.d.ts +250 -0
  19. package/lib/command/hydranium-glsp-operation-command.d.ts.map +1 -0
  20. package/lib/command/hydranium-glsp-operation-command.js +491 -0
  21. package/lib/command/hydranium-glsp-operation-command.js.map +1 -0
  22. package/lib/command/hydranium-glsp-recording-command.d.ts +26 -87
  23. package/lib/command/hydranium-glsp-recording-command.d.ts.map +1 -1
  24. package/lib/command/hydranium-glsp-recording-command.js +40 -117
  25. package/lib/command/hydranium-glsp-recording-command.js.map +1 -1
  26. package/lib/command/hydranium-glsp-undo-redo-action-handler.d.ts +23 -0
  27. package/lib/command/hydranium-glsp-undo-redo-action-handler.d.ts.map +1 -0
  28. package/lib/command/hydranium-glsp-undo-redo-action-handler.js +41 -0
  29. package/lib/command/hydranium-glsp-undo-redo-action-handler.js.map +1 -0
  30. package/lib/command/index.d.ts +5 -0
  31. package/lib/command/index.d.ts.map +1 -1
  32. package/lib/command/index.js +5 -0
  33. package/lib/command/index.js.map +1 -1
  34. package/lib/computed-bounds/hydranium-glsp-computed-bounds-action-handler.d.ts +1 -1
  35. package/lib/computed-bounds/hydranium-glsp-computed-bounds-action-handler.d.ts.map +1 -1
  36. package/lib/computed-bounds/hydranium-glsp-computed-bounds-action-handler.js +2 -2
  37. package/lib/computed-bounds/hydranium-glsp-computed-bounds-action-handler.js.map +1 -1
  38. package/lib/dispatcher/server-action-dispatcher.d.ts +25 -24
  39. package/lib/dispatcher/server-action-dispatcher.d.ts.map +1 -1
  40. package/lib/dispatcher/server-action-dispatcher.js +38 -26
  41. package/lib/dispatcher/server-action-dispatcher.js.map +1 -1
  42. package/lib/index.d.ts +1 -0
  43. package/lib/index.d.ts.map +1 -1
  44. package/lib/index.js +1 -0
  45. package/lib/index.js.map +1 -1
  46. package/lib/launcher/abstract-hydranium-glsp-diagram-module.d.ts +35 -59
  47. package/lib/launcher/abstract-hydranium-glsp-diagram-module.d.ts.map +1 -1
  48. package/lib/launcher/abstract-hydranium-glsp-diagram-module.js +60 -71
  49. package/lib/launcher/abstract-hydranium-glsp-diagram-module.js.map +1 -1
  50. package/lib/launcher/drop-notifications-to-gone-client.d.ts +23 -0
  51. package/lib/launcher/drop-notifications-to-gone-client.d.ts.map +1 -0
  52. package/lib/launcher/drop-notifications-to-gone-client.js +43 -0
  53. package/lib/launcher/drop-notifications-to-gone-client.js.map +1 -0
  54. package/lib/launcher/glsp-app-module.d.ts +1 -2
  55. package/lib/launcher/glsp-app-module.d.ts.map +1 -1
  56. package/lib/launcher/glsp-app-module.js.map +1 -1
  57. package/lib/launcher/glsp-connection-logger.d.ts +19 -0
  58. package/lib/launcher/glsp-connection-logger.d.ts.map +1 -0
  59. package/lib/launcher/glsp-connection-logger.js +24 -0
  60. package/lib/launcher/glsp-connection-logger.js.map +1 -0
  61. package/lib/launcher/glsp-server-overrides.d.ts +10 -8
  62. package/lib/launcher/glsp-server-overrides.d.ts.map +1 -1
  63. package/lib/launcher/glsp-server-overrides.js +25 -11
  64. package/lib/launcher/glsp-server-overrides.js.map +1 -1
  65. package/lib/launcher/hydranium-glsp-server.d.ts +60 -15
  66. package/lib/launcher/hydranium-glsp-server.d.ts.map +1 -1
  67. package/lib/launcher/hydranium-glsp-server.js +145 -22
  68. package/lib/launcher/hydranium-glsp-server.js.map +1 -1
  69. package/lib/launcher/index.d.ts +2 -0
  70. package/lib/launcher/index.d.ts.map +1 -1
  71. package/lib/launcher/index.js +5 -4
  72. package/lib/launcher/index.js.map +1 -1
  73. package/lib/logging/glsp-client-logger.d.ts +10 -6
  74. package/lib/logging/glsp-client-logger.d.ts.map +1 -1
  75. package/lib/logging/glsp-client-logger.js +14 -7
  76. package/lib/logging/glsp-client-logger.js.map +1 -1
  77. package/lib/messages/index.d.ts +11 -6
  78. package/lib/messages/index.d.ts.map +1 -1
  79. package/lib/messages/index.js +11 -6
  80. package/lib/messages/index.js.map +1 -1
  81. package/lib/node/start-glsp-server.d.ts +50 -15
  82. package/lib/node/start-glsp-server.d.ts.map +1 -1
  83. package/lib/node/start-glsp-server.js +97 -30
  84. package/lib/node/start-glsp-server.js.map +1 -1
  85. package/lib/state/abstract-hydranium-glsp-state.d.ts +326 -102
  86. package/lib/state/abstract-hydranium-glsp-state.d.ts.map +1 -1
  87. package/lib/state/abstract-hydranium-glsp-state.js +529 -139
  88. package/lib/state/abstract-hydranium-glsp-state.js.map +1 -1
  89. package/lib/state/diagram-status.d.ts +38 -0
  90. package/lib/state/diagram-status.d.ts.map +1 -0
  91. package/lib/state/diagram-status.js +27 -0
  92. package/lib/state/diagram-status.js.map +1 -0
  93. package/lib/state/full-text-hydranium-glsp-state.d.ts +22 -9
  94. package/lib/state/full-text-hydranium-glsp-state.d.ts.map +1 -1
  95. package/lib/state/full-text-hydranium-glsp-state.js +45 -18
  96. package/lib/state/full-text-hydranium-glsp-state.js.map +1 -1
  97. package/lib/state/hydranium-glsp-index.d.ts +40 -29
  98. package/lib/state/hydranium-glsp-index.d.ts.map +1 -1
  99. package/lib/state/hydranium-glsp-index.js +82 -45
  100. package/lib/state/hydranium-glsp-index.js.map +1 -1
  101. package/lib/state/hydranium-shared-core-services.d.ts +16 -29
  102. package/lib/state/hydranium-shared-core-services.d.ts.map +1 -1
  103. package/lib/state/hydranium-shared-core-services.js +15 -28
  104. package/lib/state/hydranium-shared-core-services.js.map +1 -1
  105. package/lib/state/index.d.ts +1 -0
  106. package/lib/state/index.d.ts.map +1 -1
  107. package/lib/state/index.js +1 -0
  108. package/lib/state/index.js.map +1 -1
  109. package/lib/state/model-ready-timeout-error.d.ts.map +1 -1
  110. package/lib/state/model-ready-timeout-error.js.map +1 -1
  111. package/lib/state/reconcile-source-model-write.d.ts +13 -27
  112. package/lib/state/reconcile-source-model-write.d.ts.map +1 -1
  113. package/lib/state/reconcile-source-model-write.js +44 -32
  114. package/lib/state/reconcile-source-model-write.js.map +1 -1
  115. package/lib/state/reconciling-multi-document-glsp-state.d.ts +125 -69
  116. package/lib/state/reconciling-multi-document-glsp-state.d.ts.map +1 -1
  117. package/lib/state/reconciling-multi-document-glsp-state.js +242 -100
  118. package/lib/state/reconciling-multi-document-glsp-state.js.map +1 -1
  119. package/lib/state/reconciling-transfer-hydranium-glsp-state.d.ts +36 -28
  120. package/lib/state/reconciling-transfer-hydranium-glsp-state.d.ts.map +1 -1
  121. package/lib/state/reconciling-transfer-hydranium-glsp-state.js +59 -42
  122. package/lib/state/reconciling-transfer-hydranium-glsp-state.js.map +1 -1
  123. package/lib/status/diagram-status-reporter.d.ts +44 -0
  124. package/lib/status/diagram-status-reporter.d.ts.map +1 -0
  125. package/lib/status/diagram-status-reporter.js +88 -0
  126. package/lib/status/diagram-status-reporter.js.map +1 -0
  127. package/lib/status/hydranium-glsp-request-model-action-handler.d.ts +27 -0
  128. package/lib/status/hydranium-glsp-request-model-action-handler.d.ts.map +1 -0
  129. package/lib/status/hydranium-glsp-request-model-action-handler.js +52 -0
  130. package/lib/status/hydranium-glsp-request-model-action-handler.js.map +1 -0
  131. package/lib/status/hydranium-glsp-set-edit-mode-action-handler.d.ts +27 -0
  132. package/lib/status/hydranium-glsp-set-edit-mode-action-handler.d.ts.map +1 -0
  133. package/lib/status/hydranium-glsp-set-edit-mode-action-handler.js +53 -0
  134. package/lib/status/hydranium-glsp-set-edit-mode-action-handler.js.map +1 -0
  135. package/lib/status/index.d.ts +12 -0
  136. package/lib/status/index.d.ts.map +1 -0
  137. package/lib/status/index.js +12 -0
  138. package/lib/status/index.js.map +1 -0
  139. package/lib/storage/hydranium-glsp-request-save-model-action-handler.d.ts +30 -0
  140. package/lib/storage/hydranium-glsp-request-save-model-action-handler.d.ts.map +1 -0
  141. package/lib/storage/hydranium-glsp-request-save-model-action-handler.js +47 -0
  142. package/lib/storage/hydranium-glsp-request-save-model-action-handler.js.map +1 -0
  143. package/lib/storage/hydranium-glsp-storage.d.ts +324 -143
  144. package/lib/storage/hydranium-glsp-storage.d.ts.map +1 -1
  145. package/lib/storage/hydranium-glsp-storage.js +569 -213
  146. package/lib/storage/hydranium-glsp-storage.js.map +1 -1
  147. package/lib/storage/index.d.ts +2 -1
  148. package/lib/storage/index.d.ts.map +1 -1
  149. package/lib/storage/index.js +2 -1
  150. package/lib/storage/index.js.map +1 -1
  151. package/lib/storage/save-delivery-policy.d.ts +51 -0
  152. package/lib/storage/save-delivery-policy.d.ts.map +1 -0
  153. package/lib/storage/{save-conflict-policy.js → save-delivery-policy.js} +7 -8
  154. package/lib/storage/save-delivery-policy.js.map +1 -0
  155. package/lib/submission/hydranium-glsp-submission-handler.d.ts +44 -4
  156. package/lib/submission/hydranium-glsp-submission-handler.d.ts.map +1 -1
  157. package/lib/submission/hydranium-glsp-submission-handler.js +82 -6
  158. package/lib/submission/hydranium-glsp-submission-handler.js.map +1 -1
  159. package/lib/testing/glsp-harness.d.ts +34 -7
  160. package/lib/testing/glsp-harness.d.ts.map +1 -1
  161. package/lib/testing/glsp-harness.js +47 -19
  162. package/lib/testing/glsp-harness.js.map +1 -1
  163. package/lib/validation/diagnostic-markers.d.ts +3 -3
  164. package/lib/validation/diagnostic-markers.d.ts.map +1 -1
  165. package/lib/validation/diagnostic-markers.js +1 -1
  166. package/lib/validation/diagnostic-markers.js.map +1 -1
  167. package/lib/validation/hydranium-glsp-model-validator.d.ts +1 -2
  168. package/lib/validation/hydranium-glsp-model-validator.d.ts.map +1 -1
  169. package/lib/validation/hydranium-glsp-model-validator.js +1 -1
  170. package/lib/validation/hydranium-glsp-model-validator.js.map +1 -1
  171. package/package.json +31 -52
  172. package/src/browser/start-glsp-server-in-worker.ts +79 -51
  173. package/src/command/diagram-edit-dropped-error.ts +51 -0
  174. package/src/command/hydranium-glsp-command-stack.ts +47 -0
  175. package/src/command/hydranium-glsp-operation-action-handler.ts +141 -0
  176. package/src/command/hydranium-glsp-operation-command.ts +602 -0
  177. package/src/command/hydranium-glsp-recording-command.ts +40 -121
  178. package/src/command/hydranium-glsp-undo-redo-action-handler.ts +29 -0
  179. package/src/command/index.ts +10 -0
  180. package/src/computed-bounds/hydranium-glsp-computed-bounds-action-handler.ts +2 -2
  181. package/src/dispatcher/server-action-dispatcher.ts +39 -31
  182. package/src/index.ts +1 -0
  183. package/src/launcher/abstract-hydranium-glsp-diagram-module.ts +79 -91
  184. package/src/launcher/drop-notifications-to-gone-client.ts +47 -0
  185. package/src/launcher/glsp-app-module.ts +1 -2
  186. package/src/launcher/glsp-connection-logger.ts +27 -0
  187. package/src/launcher/glsp-server-overrides.ts +27 -11
  188. package/src/launcher/hydranium-glsp-server.ts +153 -23
  189. package/src/launcher/index.ts +5 -4
  190. package/src/logging/glsp-client-logger.ts +16 -9
  191. package/src/messages/index.ts +16 -6
  192. package/src/node/start-glsp-server.ts +133 -40
  193. package/src/state/abstract-hydranium-glsp-state.ts +609 -154
  194. package/src/state/diagram-status.ts +41 -0
  195. package/src/state/full-text-hydranium-glsp-state.ts +46 -18
  196. package/src/state/hydranium-glsp-index.ts +85 -41
  197. package/src/state/hydranium-shared-core-services.ts +16 -29
  198. package/src/state/index.ts +1 -0
  199. package/src/state/reconcile-source-model-write.ts +51 -53
  200. package/src/state/reconciling-multi-document-glsp-state.ts +276 -102
  201. package/src/state/reconciling-transfer-hydranium-glsp-state.ts +67 -45
  202. package/src/status/diagram-status-reporter.ts +106 -0
  203. package/src/status/hydranium-glsp-request-model-action-handler.ts +43 -0
  204. package/src/status/hydranium-glsp-set-edit-mode-action-handler.ts +38 -0
  205. package/src/status/index.ts +12 -0
  206. package/src/storage/hydranium-glsp-request-save-model-action-handler.ts +40 -0
  207. package/src/storage/hydranium-glsp-storage.ts +647 -223
  208. package/src/storage/index.ts +2 -1
  209. package/src/storage/save-delivery-policy.ts +49 -0
  210. package/src/submission/hydranium-glsp-submission-handler.ts +91 -5
  211. package/src/testing/glsp-harness.ts +67 -25
  212. package/src/validation/diagnostic-markers.ts +3 -3
  213. package/src/validation/hydranium-glsp-model-validator.ts +4 -5
  214. package/lib/storage/save-conflict-policy.d.ts +0 -56
  215. package/lib/storage/save-conflict-policy.d.ts.map +0 -1
  216. package/lib/storage/save-conflict-policy.js.map +0 -1
  217. package/src/storage/save-conflict-policy.ts +0 -52
@@ -0,0 +1,51 @@
1
+ /********************************************************************************
2
+ * Copyright (c) 2026 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 { type Action, type Logger, RequestAction } from '@eclipse-glsp/server';
11
+ import { describeError, describeErrorWithStack, isConflictError } from '@hydranium/protocol';
12
+
13
+ /**
14
+ * Thrown when the reconcile of a diagram edit's write dropped it: a foreign
15
+ * edit changed a field the edit writes. Declined by design rather than failed,
16
+ * and the reconcile has logged it, so whoever ends it tells the client without
17
+ * logging it again. It never crosses a wire, so it carries no error code.
18
+ */
19
+ export class DiagramEditDroppedError extends Error {
20
+ constructor(message: string) {
21
+ super(message);
22
+ this.name = 'DiagramEditDroppedError';
23
+ }
24
+ }
25
+
26
+ /**
27
+ * Whether `error` is a {@link DiagramEditDroppedError}, by name, so one thrown
28
+ * by another installed copy of this package counts too.
29
+ */
30
+ export function isDiagramEditDroppedError(error: unknown): error is DiagramEditDroppedError {
31
+ return error instanceof Error && error.name === 'DiagramEditDroppedError';
32
+ }
33
+
34
+ /**
35
+ * Log an action that failed, once, at the level of what happened: a dropped
36
+ * edit at `debug`, since its reconcile has logged it, a conflict at `warn`
37
+ * naming its versions, since it was declined, and anything else at `error`.
38
+ * A request is named by its id too, which its client's reject carries.
39
+ */
40
+ export function logActionFailure(logger: Logger, action: Action, error: unknown): void {
41
+ const named = `'${action.kind}'${RequestAction.is(action) ? ` (${action.requestId})` : ''}`;
42
+ if (isDiagramEditDroppedError(error)) {
43
+ logger.debug(`Could not process action ${named}: ${describeError(error)}`);
44
+ } else if (isConflictError(error)) {
45
+ logger.warn(
46
+ `Could not process action ${named}: ${describeError(error)} (model v${error.baseVersion} / text v${error.actualVersion})`
47
+ );
48
+ } else {
49
+ logger.error(`Could not process action ${named}: ${describeErrorWithStack(error)}`);
50
+ }
51
+ }
@@ -0,0 +1,47 @@
1
+ /********************************************************************************
2
+ * Copyright (c) 2026 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 { DefaultCommandStack, ModelState } from '@eclipse-glsp/server';
11
+ import { type ServerSharedServices } from '@hydranium/core';
12
+ import { inject, injectable } from 'inversify';
13
+ import { HydraniumTypes } from '../state/hydranium-shared-core-services.js';
14
+
15
+ /**
16
+ * GLSP's command stack with the diagram's dirty state read from the text store:
17
+ * dirty while any document the diagram's client session has open differs from
18
+ * its file, as the store last knew the file. Undo and redo are GLSP's.
19
+ *
20
+ * GLSP's own answer counts the diagram's commands since its last save, so it
21
+ * misses every change the diagram did not make: another client's unsaved edit
22
+ * leaves it clean, and a save it did not make of a document other than the
23
+ * diagram's own leaves it dirty. Every `SetDirtyStateAction` GLSP sends reads
24
+ * this answer.
25
+ */
26
+ @injectable()
27
+ export class HydraniumGlspCommandStack extends DefaultCommandStack {
28
+ @inject(ModelState) protected readonly modelState!: ModelState;
29
+ @inject(HydraniumTypes.SharedCoreServices) protected readonly sharedServices!: ServerSharedServices;
30
+
31
+ override get isDirty(): boolean {
32
+ const textDocuments = this.sharedServices.workspace.TextDocuments;
33
+ const clientId = this.modelState.clientId;
34
+ return textDocuments.openDocuments().some(open => open.clients.includes(clientId) && textDocuments.isDirty(open.uri));
35
+ }
36
+
37
+ /**
38
+ * Lifted from `@eclipse-glsp/server` 2.7.0's `DefaultCommandStack.handleError`
39
+ * without its `error` line: the failure is rethrown, and whoever ends it
40
+ * logs it. The accompanying test pins upstream's source.
41
+ */
42
+ protected override handleError(error: unknown): never {
43
+ this.flush();
44
+ this.logger.debug('A command failed; the command stack was flushed');
45
+ throw error;
46
+ }
47
+ }
@@ -0,0 +1,141 @@
1
+ /********************************************************************************
2
+ * Copyright (c) 2026 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 {
11
+ type Action,
12
+ ActionDispatcher,
13
+ type AnyObject,
14
+ GLSPClientProxy,
15
+ GLSPServerError,
16
+ Logger,
17
+ MessageAction,
18
+ type Operation,
19
+ OperationActionHandler,
20
+ type OperationHandler
21
+ } from '@eclipse-glsp/server';
22
+ import { describeErrorWithStack } from '@hydranium/protocol';
23
+ import { inject, injectable } from 'inversify';
24
+ import { logActionFailure } from './diagram-edit-dropped-error.js';
25
+ import { HydraniumGlspOperationCommand, openOperationOf, runOperation } from './hydranium-glsp-operation-command.js';
26
+ import { type HydraniumGlspRecordingState } from './hydranium-glsp-recording-command.js';
27
+
28
+ /**
29
+ * GLSP's operation action handler, running each operation as a
30
+ * {@link HydraniumGlspOperationCommand} inside the state's `runExclusive`,
31
+ * which covers the operation, its write, the command-stack push and the
32
+ * submit, so neither another operation, an undo nor the storage's capture
33
+ * lands between them.
34
+ *
35
+ * An operation dispatched while another is open, as a handler's plain
36
+ * `dispatch` does, is queued behind it and its dispatch resolves at once;
37
+ * awaited inside the open operation, it would wait for the operation awaiting
38
+ * it. It writes, pushes and submits on its own, and a failure is reported to
39
+ * the client as GLSP reports a failed client action.
40
+ *
41
+ * Only operations are queued that way, and only while one is open, its undo's
42
+ * side effects included. Code running inside the boundary otherwise must not
43
+ * dispatch an operation and await it: a GModel factory or a submit after an
44
+ * operation, an undo's write and submit, the storage's render. Nor may any code
45
+ * inside the boundary await a dispatched undo, redo or model request, which
46
+ * take the boundary themselves. Each waits for the section awaiting it.
47
+ */
48
+ @injectable()
49
+ export class HydraniumGlspOperationActionHandler extends OperationActionHandler {
50
+ declare protected modelState: HydraniumGlspRecordingState<AnyObject>;
51
+ @inject(ActionDispatcher) protected readonly actionDispatcher!: ActionDispatcher;
52
+ @inject(Logger) protected readonly logger!: Logger;
53
+ @inject(GLSPClientProxy) protected readonly clientProxy!: GLSPClientProxy;
54
+
55
+ protected override executeHandler(operation: Operation, handler: OperationHandler): Promise<Action[]> {
56
+ const queued = openOperationOf(this.modelState) !== undefined;
57
+ const run = this.modelState.runExclusive(() => this.runOperation(operation, handler));
58
+ if (!queued) {
59
+ return run;
60
+ }
61
+ run.then(
62
+ actions => this.deliverQueued(actions),
63
+ (error: unknown) => this.reportFailure(operation, error)
64
+ );
65
+ return Promise.resolve([]);
66
+ }
67
+
68
+ /**
69
+ * Run `operation`; push it when its command was written, and submit the
70
+ * model when it executed one, written or dropped.
71
+ */
72
+ protected async runOperation(operation: Operation, handler: OperationHandler): Promise<Action[]> {
73
+ // A queued operation can find the diagram read-only by the time it runs.
74
+ if (this.modelState.isReadonly) {
75
+ return [
76
+ MessageAction.create(`Server is in readonly-mode! Could not execute operation: ${operation.kind}`, { severity: 'WARNING' })
77
+ ];
78
+ }
79
+ const command = new HydraniumGlspOperationCommand(this.modelState);
80
+ const outcome = await runOperation(command, () => handler.execute(operation));
81
+ if (outcome === 'none') {
82
+ return [];
83
+ }
84
+ if (outcome === 'executed') {
85
+ await this.executeCommand(command);
86
+ }
87
+ return this.submitModel();
88
+ }
89
+
90
+ /**
91
+ * Deliver what a queued operation answered: a message straight to the
92
+ * client, as {@link reportFailure} sends one, the rest through the
93
+ * dispatcher. A failure to deliver is logged, not reported as the
94
+ * operation's.
95
+ */
96
+ protected deliverQueued(actions: Action[]): void {
97
+ const messages = actions.filter(action => MessageAction.is(action));
98
+ messages.forEach(message => this.sendToClient(message));
99
+ this.actionDispatcher
100
+ .dispatchAll(actions.filter(action => !MessageAction.is(action)))
101
+ .catch((error: unknown) =>
102
+ this.logger.warn(`Could not deliver the result of a queued operation: ${describeErrorWithStack(error)}`)
103
+ );
104
+ }
105
+
106
+ /**
107
+ * Log `error` with {@link logActionFailure}, as the server logs a failed
108
+ * action, and send the client the error message GLSP sends for one. A
109
+ * queued operation that fails once its diagram has closed, which the
110
+ * storage's dispose marks by clearing the state's session, is logged at
111
+ * `debug` and told to no client, as the server treats an ended session.
112
+ */
113
+ protected reportFailure(operation: Operation, error: unknown): void {
114
+ // Queued only after a load registered the session, so none now means the diagram has closed.
115
+ if (this.modelState.modelSession === undefined) {
116
+ this.logger.debug(`Operation '${operation.kind}' ended with its diagram: ${describeErrorWithStack(error)}`);
117
+ return;
118
+ }
119
+ logActionFailure(this.logger, operation, error);
120
+ let message = `Could not process action: '${operation.kind}`;
121
+ let details = error instanceof Error ? error.toString() : String(error);
122
+ if (error instanceof GLSPServerError) {
123
+ details = String(error.cause);
124
+ message = error.message;
125
+ }
126
+ this.sendToClient(MessageAction.create(message, { severity: 'ERROR', details }));
127
+ }
128
+
129
+ /**
130
+ * Send `action` straight to the client, as GLSP's server sends a failed
131
+ * action's message. Sent through the dispatcher instead, an action of a
132
+ * kind the client registered no handler for is rejected.
133
+ */
134
+ protected sendToClient(action: Action): void {
135
+ try {
136
+ this.clientProxy.process({ clientId: this.modelState.clientId, action });
137
+ } catch (error: unknown) {
138
+ this.logger.warn(`Could not send '${action.kind}' to the client: ${describeErrorWithStack(error)}`);
139
+ }
140
+ }
141
+ }