@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,491 @@
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
+ import { Command, CompoundCommand } from '@eclipse-glsp/server';
10
+ import { AstUtils, isMultiReference } from '@hydranium/langium';
11
+ import { describeErrorWithStack } from '@hydranium/protocol';
12
+ import { DiagramEditDroppedError } from './diagram-edit-dropped-error.js';
13
+ const internals = new WeakMap();
14
+ /** The canonical URI of every working root an operation made, by root. */
15
+ const workingRootUris = new WeakMap();
16
+ /**
17
+ * The canonical URI of the document whose working copy `node` belongs to;
18
+ * `undefined` for a node of no copy. A copy has no `$document`, so a lookup
19
+ * that routes by a node's document routes a copy node through this instead.
20
+ */
21
+ export function workingUriOfCopy(node) {
22
+ return workingRootUris.get(AstUtils.findRootNode(node));
23
+ }
24
+ const openOperations = new WeakMap();
25
+ /** The operation open on `state`, executing, undoing or redoing its side effects; `undefined` between operations. */
26
+ export function openOperationOf(state) {
27
+ return openOperations.get(state);
28
+ }
29
+ /** Run `operation` as {@link HydraniumGlspOperationCommand} describes. */
30
+ export function runOperation(operation, create) {
31
+ return membersOf(operation).run(create);
32
+ }
33
+ function membersOf(operation) {
34
+ const members = internals.get(operation);
35
+ if (!members) {
36
+ throw new Error('Not a HydraniumGlspOperationCommand');
37
+ }
38
+ return members;
39
+ }
40
+ /**
41
+ * One GLSP operation as a transaction, and the command-stack entry that undoes
42
+ * and redoes it.
43
+ *
44
+ * {@link runOperation} executes the operation's command against copies of the
45
+ * built roots and writes their projection once; a reader of a built root never
46
+ * sees an edit its write has not committed, and an edit the write drops stays
47
+ * out of every built root. Call it inside `runExclusive`: the copies, the write
48
+ * and the capture that follows assume no other operation, undo or storage
49
+ * capture runs meanwhile.
50
+ *
51
+ * The entry holds one model transition, from the copies' projection before the
52
+ * command to their projection after it, both as the documents hold them after
53
+ * a write (see `normalizeTransition`), and the side effects that executed, in
54
+ * order: each command that does not record, a `CompoundCommand`'s children
55
+ * counted one by one, and the bridge of each recording command at any depth.
56
+ * Rollback and undo run them in reverse, redo in order. A recording command
57
+ * executed inside an open operation writes nothing, and its own undo and redo
58
+ * do nothing there.
59
+ */
60
+ export class HydraniumGlspOperationCommand {
61
+ modelState;
62
+ /** Working copies by canonical URI. */
63
+ workingRoots = new Map();
64
+ /** Built node to copy and copy to built node, across every working root, as `AstUtils.copyAstNode` records it. */
65
+ trace = new Map();
66
+ /** The source root captured when the operation opened. */
67
+ sourceRootAtOpen;
68
+ /** The version of {@link sourceRootAtOpen}, which the write is gated on. */
69
+ baseVersionAtOpen;
70
+ /**
71
+ * The primary root to capture when the operation closes: the one its write
72
+ * produced, or the document's built one after a dropped write or one the
73
+ * document already held.
74
+ */
75
+ writtenRoot;
76
+ /** Whether the write's reconcile dropped the edit. */
77
+ dropped = false;
78
+ /** The command the operation executed. */
79
+ command;
80
+ /** The side effects that executed, in execution order. */
81
+ steps = [];
82
+ /**
83
+ * The copies' projection when the operation opened, amended as documents
84
+ * join or leave the write set during it.
85
+ */
86
+ before;
87
+ transition;
88
+ /** Whether an undo or redo is running the side effects, on copies it discards. */
89
+ undoingOrRedoing = false;
90
+ constructor(modelState) {
91
+ this.modelState = modelState;
92
+ const members = {
93
+ run: create => this.run(create),
94
+ workingRootOf: (key, built) => this.workingRootOf(key, built),
95
+ existingWorkingRootOf: key => this.workingRoots.get(key),
96
+ workingUriOf: node => this.workingUriOf(node),
97
+ builtNodeOf: node => this.builtNodeOf(node),
98
+ recordWrittenRoot: root => {
99
+ this.writtenRoot = root;
100
+ },
101
+ recordDropped: current => {
102
+ this.dropped = true;
103
+ this.writtenRoot = current;
104
+ },
105
+ recordExecuted: step => {
106
+ this.steps.push(step);
107
+ },
108
+ amendBefore: update => {
109
+ if (this.before !== undefined) {
110
+ this.before = update(this.before);
111
+ }
112
+ },
113
+ assertNotDuringUndoRedo: label => {
114
+ if (this.undoingOrRedoing) {
115
+ throw new Error(`Recording command '${label}' executed during an undo or redo, which writes only the recorded transition, ` +
116
+ 'so its edit would be discarded. Execute it in an operation of its own.');
117
+ }
118
+ }
119
+ };
120
+ internals.set(this, members);
121
+ }
122
+ /**
123
+ * Open the operation, execute the command `create` makes, write the result
124
+ * once, and close the operation.
125
+ *
126
+ * `create` runs inside the operation, because handlers resolve their
127
+ * targets there. On any failure, `create`, the command or the write, the
128
+ * executed commands' side effects are undone, nothing is written, and the
129
+ * error is rethrown; after a write whose reconcile dropped the edit, the
130
+ * side effects are undone the same way and this answers `'dropped'`. The
131
+ * operation closes either way: the copies are dropped and the source root
132
+ * is captured again, with the base version, every tracked version and the
133
+ * index.
134
+ */
135
+ async run(create) {
136
+ this.open();
137
+ let recorded;
138
+ try {
139
+ this.before = await this.project();
140
+ await this.checkpoint('create');
141
+ const command = await create();
142
+ if (!command) {
143
+ return 'none';
144
+ }
145
+ await this.tracked(command).execute();
146
+ this.command = command;
147
+ await this.checkpoint('project');
148
+ const written = await this.project();
149
+ if (written !== undefined && !(await this.write(written))) {
150
+ await this.rollback();
151
+ return 'dropped';
152
+ }
153
+ if (this.before !== undefined && written !== undefined) {
154
+ recorded = { from: this.before, to: written };
155
+ }
156
+ }
157
+ catch (error) {
158
+ await this.rollback();
159
+ throw error;
160
+ }
161
+ finally {
162
+ this.close();
163
+ }
164
+ // After the write landed, so a failure here leaves it in place: the
165
+ // transition is then kept as recorded, and an undo may conflict.
166
+ try {
167
+ this.transition = recorded && (await this.modelState.normalizeTransition(recorded));
168
+ }
169
+ catch (error) {
170
+ this.modelState.logger.warn(`Normalizing an operation's transition failed: ${describeErrorWithStack(error)}`);
171
+ this.transition = recorded;
172
+ }
173
+ return 'executed';
174
+ }
175
+ /**
176
+ * Awaited where the operation, or an undo or redo of it, yields to code it
177
+ * does not control: before creating the command, before each side effect
178
+ * executes, is undone or redone, rolls back or is compensated, before
179
+ * projecting the copies, before resolving an undo or redo. Does nothing; a
180
+ * test overrides it to land a foreign edit or a failure there.
181
+ */
182
+ async checkpoint(_point) {
183
+ // A seam for tests.
184
+ }
185
+ /**
186
+ * Does nothing: {@link runOperation} executed the command; the command stack
187
+ * calls this when it pushes the entry.
188
+ */
189
+ async execute() {
190
+ // Executed by runOperation().
191
+ }
192
+ async undo() {
193
+ await this.undoOrRedo('undo');
194
+ }
195
+ async redo() {
196
+ await this.undoOrRedo('redo');
197
+ }
198
+ canUndo() {
199
+ return this.command?.canUndo?.() ?? true;
200
+ }
201
+ /** The working copy of `built`, the root of the document whose canonical URI is `key`, made on the first request. */
202
+ workingRootOf(key, built) {
203
+ let working = this.workingRoots.get(key);
204
+ if (!working) {
205
+ working = AstUtils.copyAstNode(built, (_node, _property, _refNode, _refText, original) => this.buildWorkingReference(original), this.trace);
206
+ this.rebuildWorkingMultiReferences(working);
207
+ this.workingRoots.set(key, working);
208
+ workingRootUris.set(working, key);
209
+ this.modelState.index.remapSemanticAliases(node => AstUtils.findRootNode(node) === built ? (this.trace.get(node) ?? node) : node);
210
+ }
211
+ return working;
212
+ }
213
+ /** The canonical URI of the working root `node` belongs to; `undefined` for a node of no copy. */
214
+ workingUriOf(node) {
215
+ const root = AstUtils.findRootNode(node);
216
+ for (const [key, working] of this.workingRoots) {
217
+ if (working === root) {
218
+ return key;
219
+ }
220
+ }
221
+ return undefined;
222
+ }
223
+ /**
224
+ * The built node `node` was copied from; `node` itself for a node of no copy
225
+ * and for a node the operation created.
226
+ */
227
+ builtNodeOf(node) {
228
+ if (this.workingUriOf(node) === undefined) {
229
+ return node;
230
+ }
231
+ const built = this.trace.get(node);
232
+ return built === undefined ? node : built;
233
+ }
234
+ /**
235
+ * Copy the source root, and point the index at the copy, so the nodes a
236
+ * handler resolves by id are the nodes it edits.
237
+ */
238
+ open() {
239
+ this.sourceRootAtOpen = this.modelState.sourceRoot;
240
+ this.baseVersionAtOpen = this.modelState.baseVersion;
241
+ openOperations.set(this.modelState, membersOf(this));
242
+ if (this.sourceRootAtOpen !== undefined) {
243
+ this.modelState.index.reindexSemanticElements(this.modelState.sourceRoot, this.modelState.sourceUri);
244
+ }
245
+ }
246
+ /**
247
+ * Drop the copies, move every id added through `indexSemanticElement` from
248
+ * a copy back to the built node it was copied from, and capture the source
249
+ * root again, whether or not the write changed it.
250
+ */
251
+ close() {
252
+ const copies = new Set(this.workingRoots.values());
253
+ this.modelState.index.remapSemanticAliases(node => (copies.has(AstUtils.findRootNode(node)) ? this.trace.get(node) : node));
254
+ openOperations.delete(this.modelState);
255
+ const root = this.writtenRoot ?? this.sourceRootAtOpen;
256
+ if (root !== undefined) {
257
+ this.modelState.setSourceRoot(this.modelState.sourceUri, root);
258
+ }
259
+ }
260
+ /**
261
+ * Undo the side effects of the executed commands, newest first, each step
262
+ * on its own: a step that fails is logged and the rest are still undone.
263
+ * The operation's own error is the one thrown.
264
+ */
265
+ async rollback() {
266
+ await this.runEach([...this.steps].reverse().map(step => () => step.undo()), 'Rolling back a failed operation', 'rollback');
267
+ }
268
+ /**
269
+ * Run each of `actions`, each reverting a side effect of its own: a failure
270
+ * is logged as `what` failing and the rest still run, so one step that
271
+ * cannot be reverted leaves no other step applied. The caller reports its
272
+ * own failure, not these.
273
+ */
274
+ async runEach(actions, what, point) {
275
+ for (const action of actions) {
276
+ try {
277
+ await this.checkpoint(point);
278
+ await action();
279
+ }
280
+ catch (error) {
281
+ this.modelState.logger.error(`${what} failed at one step: ${describeErrorWithStack(error)}`);
282
+ }
283
+ }
284
+ }
285
+ /**
286
+ * `command` with every side effect it executes recorded as a step: the
287
+ * command itself, or for a `CompoundCommand` each child, at any depth. A
288
+ * tracked command's own undo and redo do nothing, so a `CompoundCommand`
289
+ * reverting its children when a later one throws leaves that to the steps.
290
+ *
291
+ * The children are read from GLSP's protected `CompoundCommand.commands`;
292
+ * should that field stop being readable, a compound becomes one step and
293
+ * its children's side effects no longer interleave with the bridges.
294
+ */
295
+ tracked(command) {
296
+ const children = command instanceof CompoundCommand ? Reflect.get(command, 'commands') : undefined;
297
+ if (isCommandArray(children)) {
298
+ children.forEach((child, i) => {
299
+ children[i] = this.tracked(child);
300
+ });
301
+ return command;
302
+ }
303
+ return {
304
+ execute: async () => {
305
+ await this.checkpoint('execute');
306
+ await command.execute();
307
+ this.steps.push({ undo: () => command.undo(), redo: () => command.redo() });
308
+ },
309
+ undo: () => undefined,
310
+ redo: () => undefined,
311
+ canUndo: () => Command.canUndo(command)
312
+ };
313
+ }
314
+ /** The model projected from the working copies, cloned; `undefined` for a state that projects none. */
315
+ async project() {
316
+ const model = await this.modelState.sourceModel;
317
+ return model === undefined ? undefined : structuredClone(model);
318
+ }
319
+ /**
320
+ * Resolve the transition onto the current model, run the commands' side
321
+ * effects, then write once, gated on the versions the model was read at. A
322
+ * collision does nothing but warn; a transition with nothing left to apply,
323
+ * or one the model already holds, still runs the side effects.
324
+ *
325
+ * The caller holds `runExclusive`, which nothing here takes again.
326
+ */
327
+ async undoOrRedo(direction) {
328
+ // Captured again so the model the transition is resolved onto, the base
329
+ // a conflict reconciles from and the versions the write is gated on are
330
+ // read together.
331
+ if (this.modelState.sourceRoot !== undefined) {
332
+ this.modelState.setSourceRoot(this.modelState.sourceUri, this.modelState.sourceRoot);
333
+ }
334
+ await this.checkpoint('resolve');
335
+ let merged;
336
+ const { transition } = this.inDirection(direction);
337
+ if (transition) {
338
+ const outcome = await this.modelState.conflictResolver.resolve(transition.from, transition.to, async () => this.modelState.sourceModel);
339
+ if (outcome.status === 'merged') {
340
+ merged = outcome.merged;
341
+ }
342
+ else if (outcome.status !== 'no-op' && outcome.status !== 'already-applied') {
343
+ this.modelState.logger.warn(`${direction === 'undo' ? 'Undo' : 'Redo'} of an operation skipped (${outcome.status}); a foreign edit changed a shared field`);
344
+ return;
345
+ }
346
+ }
347
+ await this.undoOrRedoSideEffects(direction, merged);
348
+ }
349
+ /**
350
+ * Write `model` once through the state's write path, gated on the versions
351
+ * read when the operation opened, a conflict reconciled as for any write of
352
+ * the state; `false` when the reconcile dropped it.
353
+ */
354
+ async write(model) {
355
+ this.dropped = false;
356
+ await this.modelState.updateSourceModel(model, this.baseVersionAtOpen);
357
+ return !this.dropped;
358
+ }
359
+ /**
360
+ * Run the recorded steps of an undo or redo against fresh copies of the
361
+ * built roots, made on demand as in an operation and discarded unwritten,
362
+ * then write `merged`, the resolved transition, through {@link write}: that
363
+ * write is what changes the model, and a step that edits `sourceRoot` must
364
+ * not reach the root every reader shares. A recording command executed here
365
+ * throws.
366
+ *
367
+ * When a step or the write throws, or the write's reconcile drops it, the
368
+ * steps already run are run the other way, newest first, and the error is
369
+ * rethrown with nothing written; GLSP's command stack then flushes, as it
370
+ * does for any undo or redo that fails.
371
+ */
372
+ async undoOrRedoSideEffects(direction, merged) {
373
+ this.workingRoots.clear();
374
+ this.trace.clear();
375
+ this.writtenRoot = undefined;
376
+ this.undoingOrRedoing = true;
377
+ this.open();
378
+ const { steps, run } = this.inDirection(direction);
379
+ const done = [];
380
+ try {
381
+ for (const step of steps) {
382
+ await this.checkpoint(direction);
383
+ await run(step);
384
+ done.unshift(step);
385
+ }
386
+ if (merged === undefined) {
387
+ // Nothing to write, but a step may have rebuilt the document: close on its built root, not the one opened on.
388
+ this.modelState.captureBuiltRoot();
389
+ }
390
+ else if (!(await this.write(merged))) {
391
+ throw new DiagramEditDroppedError(`The ${direction} of an operation was dropped: a foreign edit changed a field it writes`);
392
+ }
393
+ }
394
+ catch (error) {
395
+ await this.compensate(done, direction);
396
+ throw error;
397
+ }
398
+ finally {
399
+ this.close();
400
+ this.undoingOrRedoing = false;
401
+ }
402
+ }
403
+ /**
404
+ * Run `steps`, which a failed undo or redo already ran, the other way, each
405
+ * on its own as {@link rollback} does; the undo or redo's own error is the
406
+ * one thrown.
407
+ */
408
+ async compensate(steps, direction) {
409
+ const { revert } = this.inDirection(direction);
410
+ await this.runEach(steps.map(step => () => revert(step)), `Reverting a failed ${direction}`, 'compensate');
411
+ }
412
+ /**
413
+ * The transition and the recorded steps as `direction` runs them: an undo
414
+ * runs the transition backwards and each step's undo, newest first, and is
415
+ * reverted by each step's redo; a redo the other way round.
416
+ */
417
+ inDirection(direction) {
418
+ if (direction === 'redo') {
419
+ return { transition: this.transition, steps: [...this.steps], run: step => step.redo(), revert: step => step.undo() };
420
+ }
421
+ return {
422
+ transition: this.transition && { from: this.transition.to, to: this.transition.from },
423
+ steps: [...this.steps].reverse(),
424
+ run: step => step.undo(),
425
+ revert: step => step.redo()
426
+ };
427
+ }
428
+ /**
429
+ * The copy's stand-in for `original`: its target is the copy of
430
+ * `original`'s target once one exists, read when asked so a copy made later
431
+ * in the operation is found, else that target itself. A handler compares a
432
+ * target by identity with nodes it resolved from a copy.
433
+ */
434
+ buildWorkingReference(original) {
435
+ const trace = this.trace;
436
+ return {
437
+ $refText: original.$refText,
438
+ $refNode: original.$refNode,
439
+ get ref() {
440
+ const target = original.ref;
441
+ return target && (trace.get(target) ?? target);
442
+ },
443
+ get error() {
444
+ return original.error;
445
+ },
446
+ get $nodeDescription() {
447
+ return original.$nodeDescription;
448
+ }
449
+ };
450
+ }
451
+ /** {@link buildWorkingReference} for a reference with several targets. */
452
+ buildWorkingMultiReference(original) {
453
+ const trace = this.trace;
454
+ return {
455
+ $refText: original.$refText,
456
+ $refNode: original.$refNode,
457
+ get items() {
458
+ return original.items.map(item => ({ ref: trace.get(item.ref) ?? item.ref, $nodeDescription: item.$nodeDescription }));
459
+ },
460
+ get error() {
461
+ return original.error;
462
+ }
463
+ };
464
+ }
465
+ /**
466
+ * Replace every multi-reference under `working` with a working one.
467
+ * `AstUtils.copyAstNode` rebuilds single references only and leaves a
468
+ * multi-reference object shared with the built root, whose targets are
469
+ * built nodes.
470
+ */
471
+ rebuildWorkingMultiReferences(working) {
472
+ for (const node of AstUtils.streamAst(working)) {
473
+ const properties = node;
474
+ for (const [name, value] of Object.entries(properties)) {
475
+ if (name.startsWith('$')) {
476
+ continue;
477
+ }
478
+ if (isMultiReference(value)) {
479
+ properties[name] = this.buildWorkingMultiReference(value);
480
+ }
481
+ else if (Array.isArray(value) && value.some(element => isMultiReference(element))) {
482
+ properties[name] = value.map((element) => isMultiReference(element) ? this.buildWorkingMultiReference(element) : element);
483
+ }
484
+ }
485
+ }
486
+ }
487
+ }
488
+ function isCommandArray(value) {
489
+ return Array.isArray(value) && value.every(element => typeof element === 'object' && element !== null && 'execute' in element);
490
+ }
491
+ //# sourceMappingURL=hydranium-glsp-operation-command.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hydranium-glsp-operation-command.js","sourceRoot":"","sources":["../../src/command/hydranium-glsp-operation-command.ts"],"names":[],"mappings":"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"}
@@ -9,6 +9,7 @@
9
9
  import { type AnyObject, type JsonModelState, JsonRecordingCommand, type MaybePromise } from '@eclipse-glsp/server';
10
10
  import { type AstNode } from '@hydranium/langium';
11
11
  import { type AbstractHydraniumGlspState } from '../state/abstract-hydranium-glsp-state.js';
12
+ import { HydraniumGlspOperationCommand } from './hydranium-glsp-operation-command.js';
12
13
  /**
13
14
  * Source-model state shape consumed by {@link HydraniumGlspRecordingCommand}.
14
15
  * The intersection ties together GLSP's read-side
@@ -21,112 +22,50 @@ import { type AbstractHydraniumGlspState } from '../state/abstract-hydranium-gls
21
22
  */
22
23
  export type HydraniumGlspRecordingState<TSourceModel extends AnyObject> = AbstractHydraniumGlspState<AstNode, TSourceModel> & JsonModelState<TSourceModel>;
23
24
  /**
24
- * GLSP {@link JsonRecordingCommand} base shared by all hydranium adopters.
25
- * Adds two things on top of GLSP's class:
26
- *
27
- * 1. A **time-labelled execute wrapper** so log lines record how long a
28
- * user-facing operation takes end-to-end — including the `postChange`
29
- * source-model update that re-parses the document. Otherwise the diff +
30
- * patch + persist work happens silently and is hard to attribute when
31
- * something is slow.
32
- * 2. A typed `state` field that exposes `updateSourceModel` for the
33
- * `postChange` bridge AND the framework `logger` for time-labelled
34
- * logging. GLSP's base class only types `modelState: JsonModelState`,
35
- * which lacks the framework's logger surface.
25
+ * GLSP {@link JsonRecordingCommand} base shared by all hydranium adopters: a
26
+ * handler mutates `sourceRoot` in the command's runnable, and the operation
27
+ * the command executes in writes the result once when it ends.
36
28
  *
37
29
  * **Optional undo/redo bridge hooks.** An adopter command can supply
38
- * `undoAction` / `redoAction` callbacks invoked alongside the patch apply, to
39
- * re-emit a side-effect the patch itself does not carry. Provided as optional
40
- * constructor args so adopters get that composition surface without
41
- * subclassing. Operation handlers that don't need bridge callbacks omit them.
30
+ * `undoAction` / `redoAction` callbacks, run when the operation is undone or
31
+ * redone and when a failed operation rolls back, to re-emit a side effect the
32
+ * model does not carry. During an undo or redo they run against throwaway
33
+ * copies, and a recording command executed there throws.
42
34
  *
43
- * **postChange semantics.** GLSP's `JsonRecordingCommand.postChange` calls
44
- * `modelState.updateSourceModel(newModel)` with the model only. The
45
- * framework lift overrides `postChange` so it also threads the based-on
46
- * version captured at command start — letting the downstream
47
- * `ModelService.update` opt into the `ConflictError` gate. Undo / redo
48
- * postChange calls run with version `undefined` (no gating): the user
49
- * authored against the recorded patch, not against a specific server
50
- * version, so re-applying it should succeed regardless of intervening
51
- * edits. The recorded patch itself encodes the semantic intent.
35
+ * A command executed outside an operation opens one of its own through
36
+ * `runExclusive`, so executing it from inside the boundary with no operation
37
+ * open deadlocks. Its undo and redo then undo and redo that operation without
38
+ * taking the boundary, which the caller holds, as the framework's undo handler
39
+ * does; taking it there would deadlock under that handler.
52
40
  */
53
41
  export declare class HydraniumGlspRecordingCommand<TSourceModel extends AnyObject> extends JsonRecordingCommand<TSourceModel> {
54
42
  /** Human-readable label for the operation; appears in the timing-pair log line. */
55
43
  protected readonly label: string;
56
- /** Optional bridge invoked alongside undo patch application; for adopters
57
- * that need to re-emit a side-effect the patch does not carry. */
44
+ /** Optional bridge invoked when the command is undone; for adopters
45
+ * that need to re-emit a side-effect the model does not carry. */
58
46
  protected readonly undoAction?: (() => MaybePromise<void>) | undefined;
59
- /** Optional bridge invoked alongside redo patch application. */
47
+ /** Optional bridge invoked when the command is redone. */
60
48
  protected readonly redoAction?: (() => MaybePromise<void>) | undefined;
61
49
  protected modelState: HydraniumGlspRecordingState<TSourceModel>;
62
- /**
63
- * Based-on version captured at {@link execute} start; threaded into
64
- * {@link postChange} so {@link AbstractHydraniumGlspState.updateSourceModel}
65
- * sees the version the user authored against. Cleared after `execute`
66
- * returns so undo / redo paths fall through to `updateSourceModel`
67
- * without a version (no gating).
68
- */
69
- protected activeVersion?: number;
70
- /**
71
- * Source-model snapshots captured at {@link execute} — the state the
72
- * command left ({@link afterSnapshot}) and the state it started from
73
- * ({@link beforeSnapshot}). {@link undo} / {@link redo} reconcile the
74
- * recorded transition against the *current* source model via the state's
75
- * {@link AbstractHydraniumGlspState.conflictResolver}, so under the default
76
- * reconciling policy a concurrent edit to another field survives and a
77
- * same-field collision is dropped rather than clobbered.
78
- */
79
- protected beforeSnapshot?: TSourceModel;
80
- protected afterSnapshot?: TSourceModel;
50
+ /** The operation this command opened, when it executed outside one. */
51
+ protected ownOperation?: HydraniumGlspOperationCommand<TSourceModel>;
81
52
  constructor(modelState: HydraniumGlspRecordingState<TSourceModel>,
82
53
  /** Human-readable label for the operation; appears in the timing-pair log line. */
83
54
  label: string, doExecute: () => MaybePromise<void>,
84
- /** Optional bridge invoked alongside undo patch application; for adopters
85
- * that need to re-emit a side-effect the patch does not carry. */
55
+ /** Optional bridge invoked when the command is undone; for adopters
56
+ * that need to re-emit a side-effect the model does not carry. */
86
57
  undoAction?: (() => MaybePromise<void>) | undefined,
87
- /** Optional bridge invoked alongside redo patch application. */
58
+ /** Optional bridge invoked when the command is redone. */
88
59
  redoAction?: (() => MaybePromise<void>) | undefined);
89
- /**
90
- * Time-label the full execute path: pre-state snapshot + `doExecute` +
91
- * post-state snapshot + patch-derive + `postChange` (which writes back
92
- * via {@link AbstractHydraniumGlspState.updateSourceModel}). The label combines
93
- * the operation name with the source-uri-stamped logger.
94
- *
95
- * Captures {@link AbstractHydraniumGlspState.version} at start so {@link postChange}
96
- * can thread the based-on version into `updateSourceModel`. The capture
97
- * is `try`/`finally`-scoped so undo / redo paths invoked later do not
98
- * see a stale captured version.
99
- */
100
60
  execute(): Promise<void>;
61
+ /** Writes nothing: the operation the command executes in writes once when it ends. */
62
+ protected postChange(_newModel: TSourceModel): void;
101
63
  /**
102
- * Override of GLSP's {@link JsonRecordingCommand.postChange} so the
103
- * call to {@link AbstractHydraniumGlspState.updateSourceModel} threads the
104
- * captured based-on version alongside the new model.
105
- *
106
- * During {@link execute} the version is the snapshot captured at
107
- * command start; during {@link undo} / {@link redo} it is `undefined`
108
- * — replaying a recorded patch does not author against a specific
109
- * server version, so no gate applies.
110
- */
111
- protected postChange(newModel: TSourceModel): MaybePromise<void>;
112
- /**
113
- * Reconcile the recorded `after → before` transition against the
114
- * *current* source model via the state's
115
- * {@link AbstractHydraniumGlspState.conflictResolver}, invoke the optional adopter
116
- * `undoAction`, and persist via `postChange`. Under the default reconciling
117
- * policy the revert is replayed guarded by `test` ops, so a concurrent edit
118
- * to another field is preserved (merged) and a same-field collision is
119
- * dropped rather than clobbered; a force policy clobbers (last-writer-wins).
120
- * On anything but a clean merge the undo is a logged no-op — the side-effect
121
- * bridge and `postChange` only run on a merged result, preserving a
122
- * "bridge before commit" order.
64
+ * Inside an open operation does nothing: the operation runs the bridge, once
65
+ * for every recording command that executed.
123
66
  */
124
67
  undo(): Promise<void>;
125
- /**
126
- * Reconcile the recorded `before → after` transition against the current
127
- * source model, invoke the optional adopter `redoAction`, and persist via
128
- * `postChange`. Same guarded merge / drop semantics as {@link undo}.
129
- */
68
+ /** Inside an open operation does nothing, as {@link undo}. */
130
69
  redo(): Promise<void>;
131
70
  }
132
71
  //# sourceMappingURL=hydranium-glsp-recording-command.d.ts.map