@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.
- package/README.md +80 -88
- package/lib/browser/start-glsp-server-in-worker.d.ts +43 -42
- package/lib/browser/start-glsp-server-in-worker.d.ts.map +1 -1
- package/lib/browser/start-glsp-server-in-worker.js +62 -13
- package/lib/browser/start-glsp-server-in-worker.js.map +1 -1
- package/lib/command/diagram-edit-dropped-error.d.ts +31 -0
- package/lib/command/diagram-edit-dropped-error.d.ts.map +1 -0
- package/lib/command/diagram-edit-dropped-error.js +48 -0
- package/lib/command/diagram-edit-dropped-error.js.map +1 -0
- package/lib/command/hydranium-glsp-command-stack.d.ts +33 -0
- package/lib/command/hydranium-glsp-command-stack.d.ts.map +1 -0
- package/lib/command/hydranium-glsp-command-stack.js +63 -0
- package/lib/command/hydranium-glsp-command-stack.js.map +1 -0
- package/lib/command/hydranium-glsp-operation-action-handler.d.ts +64 -0
- package/lib/command/hydranium-glsp-operation-action-handler.d.ts.map +1 -0
- package/lib/command/hydranium-glsp-operation-action-handler.js +142 -0
- package/lib/command/hydranium-glsp-operation-action-handler.js.map +1 -0
- package/lib/command/hydranium-glsp-operation-command.d.ts +250 -0
- package/lib/command/hydranium-glsp-operation-command.d.ts.map +1 -0
- package/lib/command/hydranium-glsp-operation-command.js +491 -0
- package/lib/command/hydranium-glsp-operation-command.js.map +1 -0
- package/lib/command/hydranium-glsp-recording-command.d.ts +26 -87
- package/lib/command/hydranium-glsp-recording-command.d.ts.map +1 -1
- package/lib/command/hydranium-glsp-recording-command.js +40 -117
- package/lib/command/hydranium-glsp-recording-command.js.map +1 -1
- package/lib/command/hydranium-glsp-undo-redo-action-handler.d.ts +23 -0
- package/lib/command/hydranium-glsp-undo-redo-action-handler.d.ts.map +1 -0
- package/lib/command/hydranium-glsp-undo-redo-action-handler.js +41 -0
- package/lib/command/hydranium-glsp-undo-redo-action-handler.js.map +1 -0
- package/lib/command/index.d.ts +5 -0
- package/lib/command/index.d.ts.map +1 -1
- package/lib/command/index.js +5 -0
- package/lib/command/index.js.map +1 -1
- package/lib/computed-bounds/hydranium-glsp-computed-bounds-action-handler.d.ts +1 -1
- package/lib/computed-bounds/hydranium-glsp-computed-bounds-action-handler.d.ts.map +1 -1
- package/lib/computed-bounds/hydranium-glsp-computed-bounds-action-handler.js +2 -2
- package/lib/computed-bounds/hydranium-glsp-computed-bounds-action-handler.js.map +1 -1
- package/lib/dispatcher/server-action-dispatcher.d.ts +25 -24
- package/lib/dispatcher/server-action-dispatcher.d.ts.map +1 -1
- package/lib/dispatcher/server-action-dispatcher.js +38 -26
- package/lib/dispatcher/server-action-dispatcher.js.map +1 -1
- package/lib/index.d.ts +1 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +1 -0
- package/lib/index.js.map +1 -1
- package/lib/launcher/abstract-hydranium-glsp-diagram-module.d.ts +35 -59
- package/lib/launcher/abstract-hydranium-glsp-diagram-module.d.ts.map +1 -1
- package/lib/launcher/abstract-hydranium-glsp-diagram-module.js +60 -71
- package/lib/launcher/abstract-hydranium-glsp-diagram-module.js.map +1 -1
- package/lib/launcher/drop-notifications-to-gone-client.d.ts +23 -0
- package/lib/launcher/drop-notifications-to-gone-client.d.ts.map +1 -0
- package/lib/launcher/drop-notifications-to-gone-client.js +43 -0
- package/lib/launcher/drop-notifications-to-gone-client.js.map +1 -0
- package/lib/launcher/glsp-app-module.d.ts +1 -2
- package/lib/launcher/glsp-app-module.d.ts.map +1 -1
- package/lib/launcher/glsp-app-module.js.map +1 -1
- package/lib/launcher/glsp-connection-logger.d.ts +19 -0
- package/lib/launcher/glsp-connection-logger.d.ts.map +1 -0
- package/lib/launcher/glsp-connection-logger.js +24 -0
- package/lib/launcher/glsp-connection-logger.js.map +1 -0
- package/lib/launcher/glsp-server-overrides.d.ts +10 -8
- package/lib/launcher/glsp-server-overrides.d.ts.map +1 -1
- package/lib/launcher/glsp-server-overrides.js +25 -11
- package/lib/launcher/glsp-server-overrides.js.map +1 -1
- package/lib/launcher/hydranium-glsp-server.d.ts +60 -15
- package/lib/launcher/hydranium-glsp-server.d.ts.map +1 -1
- package/lib/launcher/hydranium-glsp-server.js +145 -22
- package/lib/launcher/hydranium-glsp-server.js.map +1 -1
- package/lib/launcher/index.d.ts +2 -0
- package/lib/launcher/index.d.ts.map +1 -1
- package/lib/launcher/index.js +5 -4
- package/lib/launcher/index.js.map +1 -1
- package/lib/logging/glsp-client-logger.d.ts +10 -6
- package/lib/logging/glsp-client-logger.d.ts.map +1 -1
- package/lib/logging/glsp-client-logger.js +14 -7
- package/lib/logging/glsp-client-logger.js.map +1 -1
- package/lib/messages/index.d.ts +11 -6
- package/lib/messages/index.d.ts.map +1 -1
- package/lib/messages/index.js +11 -6
- package/lib/messages/index.js.map +1 -1
- package/lib/node/start-glsp-server.d.ts +50 -15
- package/lib/node/start-glsp-server.d.ts.map +1 -1
- package/lib/node/start-glsp-server.js +97 -30
- package/lib/node/start-glsp-server.js.map +1 -1
- package/lib/state/abstract-hydranium-glsp-state.d.ts +326 -102
- package/lib/state/abstract-hydranium-glsp-state.d.ts.map +1 -1
- package/lib/state/abstract-hydranium-glsp-state.js +529 -139
- package/lib/state/abstract-hydranium-glsp-state.js.map +1 -1
- package/lib/state/diagram-status.d.ts +38 -0
- package/lib/state/diagram-status.d.ts.map +1 -0
- package/lib/state/diagram-status.js +27 -0
- package/lib/state/diagram-status.js.map +1 -0
- package/lib/state/full-text-hydranium-glsp-state.d.ts +22 -9
- package/lib/state/full-text-hydranium-glsp-state.d.ts.map +1 -1
- package/lib/state/full-text-hydranium-glsp-state.js +45 -18
- package/lib/state/full-text-hydranium-glsp-state.js.map +1 -1
- package/lib/state/hydranium-glsp-index.d.ts +40 -29
- package/lib/state/hydranium-glsp-index.d.ts.map +1 -1
- package/lib/state/hydranium-glsp-index.js +82 -45
- package/lib/state/hydranium-glsp-index.js.map +1 -1
- package/lib/state/hydranium-shared-core-services.d.ts +16 -29
- package/lib/state/hydranium-shared-core-services.d.ts.map +1 -1
- package/lib/state/hydranium-shared-core-services.js +15 -28
- package/lib/state/hydranium-shared-core-services.js.map +1 -1
- package/lib/state/index.d.ts +1 -0
- package/lib/state/index.d.ts.map +1 -1
- package/lib/state/index.js +1 -0
- package/lib/state/index.js.map +1 -1
- package/lib/state/model-ready-timeout-error.d.ts.map +1 -1
- package/lib/state/model-ready-timeout-error.js.map +1 -1
- package/lib/state/reconcile-source-model-write.d.ts +13 -27
- package/lib/state/reconcile-source-model-write.d.ts.map +1 -1
- package/lib/state/reconcile-source-model-write.js +44 -32
- package/lib/state/reconcile-source-model-write.js.map +1 -1
- package/lib/state/reconciling-multi-document-glsp-state.d.ts +125 -69
- package/lib/state/reconciling-multi-document-glsp-state.d.ts.map +1 -1
- package/lib/state/reconciling-multi-document-glsp-state.js +242 -100
- package/lib/state/reconciling-multi-document-glsp-state.js.map +1 -1
- package/lib/state/reconciling-transfer-hydranium-glsp-state.d.ts +36 -28
- package/lib/state/reconciling-transfer-hydranium-glsp-state.d.ts.map +1 -1
- package/lib/state/reconciling-transfer-hydranium-glsp-state.js +59 -42
- package/lib/state/reconciling-transfer-hydranium-glsp-state.js.map +1 -1
- package/lib/status/diagram-status-reporter.d.ts +44 -0
- package/lib/status/diagram-status-reporter.d.ts.map +1 -0
- package/lib/status/diagram-status-reporter.js +88 -0
- package/lib/status/diagram-status-reporter.js.map +1 -0
- package/lib/status/hydranium-glsp-request-model-action-handler.d.ts +27 -0
- package/lib/status/hydranium-glsp-request-model-action-handler.d.ts.map +1 -0
- package/lib/status/hydranium-glsp-request-model-action-handler.js +52 -0
- package/lib/status/hydranium-glsp-request-model-action-handler.js.map +1 -0
- package/lib/status/hydranium-glsp-set-edit-mode-action-handler.d.ts +27 -0
- package/lib/status/hydranium-glsp-set-edit-mode-action-handler.d.ts.map +1 -0
- package/lib/status/hydranium-glsp-set-edit-mode-action-handler.js +53 -0
- package/lib/status/hydranium-glsp-set-edit-mode-action-handler.js.map +1 -0
- package/lib/status/index.d.ts +12 -0
- package/lib/status/index.d.ts.map +1 -0
- package/lib/status/index.js +12 -0
- package/lib/status/index.js.map +1 -0
- package/lib/storage/hydranium-glsp-request-save-model-action-handler.d.ts +30 -0
- package/lib/storage/hydranium-glsp-request-save-model-action-handler.d.ts.map +1 -0
- package/lib/storage/hydranium-glsp-request-save-model-action-handler.js +47 -0
- package/lib/storage/hydranium-glsp-request-save-model-action-handler.js.map +1 -0
- package/lib/storage/hydranium-glsp-storage.d.ts +324 -143
- package/lib/storage/hydranium-glsp-storage.d.ts.map +1 -1
- package/lib/storage/hydranium-glsp-storage.js +569 -213
- package/lib/storage/hydranium-glsp-storage.js.map +1 -1
- package/lib/storage/index.d.ts +2 -1
- package/lib/storage/index.d.ts.map +1 -1
- package/lib/storage/index.js +2 -1
- package/lib/storage/index.js.map +1 -1
- package/lib/storage/save-delivery-policy.d.ts +51 -0
- package/lib/storage/save-delivery-policy.d.ts.map +1 -0
- package/lib/storage/{save-conflict-policy.js → save-delivery-policy.js} +7 -8
- package/lib/storage/save-delivery-policy.js.map +1 -0
- package/lib/submission/hydranium-glsp-submission-handler.d.ts +44 -4
- package/lib/submission/hydranium-glsp-submission-handler.d.ts.map +1 -1
- package/lib/submission/hydranium-glsp-submission-handler.js +82 -6
- package/lib/submission/hydranium-glsp-submission-handler.js.map +1 -1
- package/lib/testing/glsp-harness.d.ts +34 -7
- package/lib/testing/glsp-harness.d.ts.map +1 -1
- package/lib/testing/glsp-harness.js +47 -19
- package/lib/testing/glsp-harness.js.map +1 -1
- package/lib/validation/diagnostic-markers.d.ts +3 -3
- package/lib/validation/diagnostic-markers.d.ts.map +1 -1
- package/lib/validation/diagnostic-markers.js +1 -1
- package/lib/validation/diagnostic-markers.js.map +1 -1
- package/lib/validation/hydranium-glsp-model-validator.d.ts +1 -2
- package/lib/validation/hydranium-glsp-model-validator.d.ts.map +1 -1
- package/lib/validation/hydranium-glsp-model-validator.js +1 -1
- package/lib/validation/hydranium-glsp-model-validator.js.map +1 -1
- package/package.json +31 -52
- package/src/browser/start-glsp-server-in-worker.ts +79 -51
- package/src/command/diagram-edit-dropped-error.ts +51 -0
- package/src/command/hydranium-glsp-command-stack.ts +47 -0
- package/src/command/hydranium-glsp-operation-action-handler.ts +141 -0
- package/src/command/hydranium-glsp-operation-command.ts +602 -0
- package/src/command/hydranium-glsp-recording-command.ts +40 -121
- package/src/command/hydranium-glsp-undo-redo-action-handler.ts +29 -0
- package/src/command/index.ts +10 -0
- package/src/computed-bounds/hydranium-glsp-computed-bounds-action-handler.ts +2 -2
- package/src/dispatcher/server-action-dispatcher.ts +39 -31
- package/src/index.ts +1 -0
- package/src/launcher/abstract-hydranium-glsp-diagram-module.ts +79 -91
- package/src/launcher/drop-notifications-to-gone-client.ts +47 -0
- package/src/launcher/glsp-app-module.ts +1 -2
- package/src/launcher/glsp-connection-logger.ts +27 -0
- package/src/launcher/glsp-server-overrides.ts +27 -11
- package/src/launcher/hydranium-glsp-server.ts +153 -23
- package/src/launcher/index.ts +5 -4
- package/src/logging/glsp-client-logger.ts +16 -9
- package/src/messages/index.ts +16 -6
- package/src/node/start-glsp-server.ts +133 -40
- package/src/state/abstract-hydranium-glsp-state.ts +609 -154
- package/src/state/diagram-status.ts +41 -0
- package/src/state/full-text-hydranium-glsp-state.ts +46 -18
- package/src/state/hydranium-glsp-index.ts +85 -41
- package/src/state/hydranium-shared-core-services.ts +16 -29
- package/src/state/index.ts +1 -0
- package/src/state/reconcile-source-model-write.ts +51 -53
- package/src/state/reconciling-multi-document-glsp-state.ts +276 -102
- package/src/state/reconciling-transfer-hydranium-glsp-state.ts +67 -45
- package/src/status/diagram-status-reporter.ts +106 -0
- package/src/status/hydranium-glsp-request-model-action-handler.ts +43 -0
- package/src/status/hydranium-glsp-set-edit-mode-action-handler.ts +38 -0
- package/src/status/index.ts +12 -0
- package/src/storage/hydranium-glsp-request-save-model-action-handler.ts +40 -0
- package/src/storage/hydranium-glsp-storage.ts +647 -223
- package/src/storage/index.ts +2 -1
- package/src/storage/save-delivery-policy.ts +49 -0
- package/src/submission/hydranium-glsp-submission-handler.ts +91 -5
- package/src/testing/glsp-harness.ts +67 -25
- package/src/validation/diagnostic-markers.ts +3 -3
- package/src/validation/hydranium-glsp-model-validator.ts +4 -5
- package/lib/storage/save-conflict-policy.d.ts +0 -56
- package/lib/storage/save-conflict-policy.d.ts.map +0 -1
- package/lib/storage/save-conflict-policy.js.map +0 -1
- package/src/storage/save-conflict-policy.ts +0 -52
package/src/storage/index.ts
CHANGED
|
@@ -7,5 +7,6 @@
|
|
|
7
7
|
* SPDX-License-Identifier: MIT
|
|
8
8
|
********************************************************************************/
|
|
9
9
|
|
|
10
|
+
export * from './hydranium-glsp-request-save-model-action-handler.js';
|
|
10
11
|
export * from './hydranium-glsp-storage.js';
|
|
11
|
-
export * from './save-
|
|
12
|
+
export * from './save-delivery-policy.js';
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/********************************************************************************
|
|
2
|
+
* Copyright (c) 2026 CrossBreeze, EclipseSource and others.
|
|
3
|
+
*
|
|
4
|
+
* This program and the accompanying materials are made available under the
|
|
5
|
+
* terms of the MIT License which is available in the project root.
|
|
6
|
+
*
|
|
7
|
+
* SPDX-License-Identifier: MIT
|
|
8
|
+
********************************************************************************/
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* How `HydraniumGlspStorage.saveSourceModel` delivers its result: whether the
|
|
12
|
+
* GLSP save action awaits the write, and what happens on failure.
|
|
13
|
+
*
|
|
14
|
+
* The two are not independent — fire-and-forget plus rethrow would leave an
|
|
15
|
+
* unhandled rejection — so each arm bundles them into one coherent, nameable
|
|
16
|
+
* policy an adopter selects whole. It is a *selection of configuration*,
|
|
17
|
+
* delivered as a bound option (see the {@link SaveDeliveryPolicy} symbol) rather
|
|
18
|
+
* than a behaviour hook.
|
|
19
|
+
*
|
|
20
|
+
* **Neither arm guards on a base version.** A save flushes the store's
|
|
21
|
+
* settled text rather than authoring from the diagram's captured model, and the
|
|
22
|
+
* store already holds every other client's change — so a guard here refuses a
|
|
23
|
+
* write whose content is already correct. The gate that does exist sits on the
|
|
24
|
+
* update path, per operation, where the diagram authors.
|
|
25
|
+
*/
|
|
26
|
+
export type SaveDeliveryPolicy =
|
|
27
|
+
/**
|
|
28
|
+
* Await the write and the language client's settle, and propagate any
|
|
29
|
+
* failure to the GLSP save action. The default. A language client that
|
|
30
|
+
* does not answer holds the first such save, and the diagram's queued
|
|
31
|
+
* actions, for the settle bound; saves after it do not wait for it again.
|
|
32
|
+
*/
|
|
33
|
+
| { kind: 'await' }
|
|
34
|
+
/**
|
|
35
|
+
* Fire-and-forget, logging and swallowing every failure. Correct when a
|
|
36
|
+
* failed diagram save must neither block the action nor surface as an error.
|
|
37
|
+
*/
|
|
38
|
+
| { kind: 'fire-and-forget' };
|
|
39
|
+
|
|
40
|
+
/** The policy applied when no {@link SaveDeliveryPolicy} option is bound. */
|
|
41
|
+
export const DEFAULT_SAVE_DELIVERY_POLICY: SaveDeliveryPolicy = { kind: 'await' };
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* DI token for the {@link SaveDeliveryPolicy} option. Bind a constant value in a
|
|
45
|
+
* `DiagramModule` to select a non-default policy; left unbound,
|
|
46
|
+
* `HydraniumGlspStorage` falls back to {@link DEFAULT_SAVE_DELIVERY_POLICY}.
|
|
47
|
+
* Shares its name with the type, the way a `class` is both a value and a type.
|
|
48
|
+
*/
|
|
49
|
+
export const SaveDeliveryPolicy = Symbol('SaveDeliveryPolicy');
|
|
@@ -12,15 +12,20 @@ import {
|
|
|
12
12
|
type DirtyStateChangeReason,
|
|
13
13
|
type GModelRootSchema,
|
|
14
14
|
type LayoutOperation,
|
|
15
|
+
MarkersReason,
|
|
15
16
|
ModelState,
|
|
16
17
|
ModelSubmissionHandler,
|
|
18
|
+
type ModelValidator,
|
|
17
19
|
SetDirtyStateAction,
|
|
20
|
+
SetMarkersAction,
|
|
18
21
|
type SetModelAction
|
|
19
22
|
} from '@eclipse-glsp/server';
|
|
20
23
|
import { IntegrityService } from '@hydranium/core';
|
|
21
24
|
import { inject, injectable } from 'inversify';
|
|
22
25
|
import { type AstNode, type DocumentState } from '@hydranium/langium';
|
|
26
|
+
import { describeErrorWithStack } from '@hydranium/protocol';
|
|
23
27
|
import { type AbstractHydraniumGlspState } from '../state/abstract-hydranium-glsp-state.js';
|
|
28
|
+
import { DiagramStatus } from '../state/diagram-status.js';
|
|
24
29
|
|
|
25
30
|
/**
|
|
26
31
|
* GLSP {@link ModelSubmissionHandler} base shared by all hydranium adopters.
|
|
@@ -79,6 +84,8 @@ export class HydraniumGlspSubmissionHandler<TRoot extends AstNode, TSourceModel
|
|
|
79
84
|
}
|
|
80
85
|
|
|
81
86
|
override async submitModel(reason?: DirtyStateChangeReason, layout?: LayoutOperation): Promise<Action[]> {
|
|
87
|
+
// Numbered before the first await, so a caller can predict it.
|
|
88
|
+
const submission = ++this._startedSubmissions;
|
|
82
89
|
if (this.readyEvent !== undefined) {
|
|
83
90
|
// Adopters with on-build integrity rules wait so the GModel-factory walk sees
|
|
84
91
|
// a settled AST; otherwise the GModel could include elements the build pass is
|
|
@@ -86,8 +93,15 @@ export class HydraniumGlspSubmissionHandler<TRoot extends AstNode, TSourceModel
|
|
|
86
93
|
// via onReadyRefreshed.
|
|
87
94
|
await this.modelState.ready(this.readyEvent);
|
|
88
95
|
}
|
|
89
|
-
const
|
|
96
|
+
const submitted = super.submitModel(reason, layout);
|
|
97
|
+
// Read before awaiting: GLSP bumps the revision synchronously, and another
|
|
98
|
+
// submission may run once this one yields.
|
|
99
|
+
const revision = this.modelState.root?.revision;
|
|
100
|
+
const actions = await submitted;
|
|
101
|
+
this.previousSubmission = { signature: this._lastSubmittedSignature, revision: this.lastSubmittedRevision };
|
|
90
102
|
this._lastSubmittedSignature = this.signatureOf(actions);
|
|
103
|
+
this.lastSubmittedRevision = revision;
|
|
104
|
+
this.lastCompletedSubmission = submission;
|
|
91
105
|
this.logSubmit(reason, actions);
|
|
92
106
|
return actions;
|
|
93
107
|
}
|
|
@@ -107,6 +121,78 @@ export class HydraniumGlspSubmissionHandler<TRoot extends AstNode, TSourceModel
|
|
|
107
121
|
|
|
108
122
|
protected _lastSubmittedSignature?: string;
|
|
109
123
|
|
|
124
|
+
/** GModel revision of the last submission, whatever its reason. */
|
|
125
|
+
protected lastSubmittedRevision?: number;
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* How many submissions have started, whatever their reason. A caller that
|
|
129
|
+
* may drop the submission it is about to start names it to
|
|
130
|
+
* {@link withdrawLastSubmission} as this count plus one.
|
|
131
|
+
*/
|
|
132
|
+
get startedSubmissions(): number {
|
|
133
|
+
return this._startedSubmissions;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
protected _startedSubmissions = 0;
|
|
137
|
+
|
|
138
|
+
/** The number of the submission that completed last. */
|
|
139
|
+
protected lastCompletedSubmission?: number;
|
|
140
|
+
|
|
141
|
+
/** What {@link withdrawLastSubmission} restores. */
|
|
142
|
+
protected previousSubmission?: { readonly signature?: string; readonly revision?: number };
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Take back the latest submission, which the caller drops unsent because it
|
|
146
|
+
* matches the one before. `submission` is its number, the
|
|
147
|
+
* {@link startedSubmissions} count when it started. GLSP bumped the GModel
|
|
148
|
+
* revision for it; left bumped, the client's measured bounds for the graph
|
|
149
|
+
* it already has arrive stale and its update is never sent. A no-op once
|
|
150
|
+
* another submission has finished or rebuilt the root since, which the
|
|
151
|
+
* client is given instead.
|
|
152
|
+
*
|
|
153
|
+
* An override of {@link submitModel} may return its own array. If it awaits
|
|
154
|
+
* before calling `super.submitModel`, another submission can take the number
|
|
155
|
+
* first, and the withdraw is then a no-op.
|
|
156
|
+
*/
|
|
157
|
+
withdrawLastSubmission(submission: number): void {
|
|
158
|
+
const previous = this.previousSubmission;
|
|
159
|
+
if (!previous || submission !== this.lastCompletedSubmission || this.modelState.root?.revision !== this.lastSubmittedRevision) {
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
this.previousSubmission = undefined;
|
|
163
|
+
this._lastSubmittedSignature = previous.signature;
|
|
164
|
+
this.lastSubmittedRevision = previous.revision;
|
|
165
|
+
const root = this.modelState.root;
|
|
166
|
+
if (root && previous.revision !== undefined) {
|
|
167
|
+
root.revision = previous.revision;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Live validation as the {@link DiagramStatus.VALIDATION} status, rather than
|
|
173
|
+
* GLSP's own status writes, whose closing clear erases any status still in
|
|
174
|
+
* force, such as the reason a diagram is read-only.
|
|
175
|
+
*
|
|
176
|
+
* Never rejects: GLSP runs it from a debounce that drops the result, so a
|
|
177
|
+
* failure here would go unhandled. A validator that throws is logged as an
|
|
178
|
+
* error, markers that cannot be sent as a warning.
|
|
179
|
+
*/
|
|
180
|
+
protected override async performLiveValidation(validator: ModelValidator): Promise<void> {
|
|
181
|
+
this.modelState.setStatus(DiagramStatus.VALIDATION, { message: 'Validate Model...', severity: 'INFO' });
|
|
182
|
+
try {
|
|
183
|
+
const markers = await validator.validate([this.modelState.root], MarkersReason.LIVE);
|
|
184
|
+
await this.actionDispatcher
|
|
185
|
+
.dispatch(SetMarkersAction.create(markers, { reason: MarkersReason.LIVE }))
|
|
186
|
+
.catch((error: unknown) =>
|
|
187
|
+
this.modelState.logger.warn(`Could not send the live-validation markers: ${describeErrorWithStack(error)}`)
|
|
188
|
+
);
|
|
189
|
+
} catch (error: unknown) {
|
|
190
|
+
this.modelState.logger.error(`Live validation failed: ${describeErrorWithStack(error)}`);
|
|
191
|
+
} finally {
|
|
192
|
+
this.modelState.setStatus(DiagramStatus.VALIDATION, undefined);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
110
196
|
/**
|
|
111
197
|
* Serialise the model-bearing actions of a submission into a comparable
|
|
112
198
|
* signature.
|
|
@@ -134,9 +220,9 @@ export class HydraniumGlspSubmissionHandler<TRoot extends AstNode, TSourceModel
|
|
|
134
220
|
}
|
|
135
221
|
|
|
136
222
|
/**
|
|
137
|
-
* Logs the {@link SetModelAction} dispatch so
|
|
138
|
-
* `requestModel → setModel` handshake is
|
|
139
|
-
*
|
|
223
|
+
* Logs the {@link SetModelAction} dispatch, so a diagram's initial
|
|
224
|
+
* `requestModel → setModel` handshake is a milestone in the server log; the
|
|
225
|
+
* submit and computed-bounds lines around it are diagnosis.
|
|
140
226
|
*/
|
|
141
227
|
protected override createSetModeAction(newRoot: GModelRootSchema): SetModelAction {
|
|
142
228
|
const action = super.createSetModeAction(newRoot);
|
|
@@ -151,7 +237,7 @@ export class HydraniumGlspSubmissionHandler<TRoot extends AstNode, TSourceModel
|
|
|
151
237
|
const gChildren = root?.children?.length ?? 0;
|
|
152
238
|
const sourceRoot = this.modelState.sourceRoot;
|
|
153
239
|
const kinds = actions.map(a => a.kind).join(',');
|
|
154
|
-
this.modelState.logger.
|
|
240
|
+
this.modelState.logger.debug(
|
|
155
241
|
`Submit model [reason=${reason ?? 'initial'}, actions=[${kinds}], ` +
|
|
156
242
|
`gmodel={type=${root?.type ?? 'none'}, children=${gChildren}}, ` +
|
|
157
243
|
`ast={${this.formatSourceRoot(sourceRoot)}}]`
|
|
@@ -10,16 +10,20 @@
|
|
|
10
10
|
import 'reflect-metadata';
|
|
11
11
|
import {
|
|
12
12
|
type Action,
|
|
13
|
+
ActionDispatchScope,
|
|
13
14
|
type ActionMessage,
|
|
14
15
|
ClientSessionManager,
|
|
15
16
|
EndProgressAction,
|
|
16
17
|
GLSPClientProxy,
|
|
17
18
|
GLSPServer,
|
|
19
|
+
MessageAction,
|
|
18
20
|
ModelState,
|
|
21
|
+
RejectAction,
|
|
19
22
|
RequestBoundsAction,
|
|
20
23
|
RequestModelAction,
|
|
21
24
|
SOURCE_URI_ARG,
|
|
22
25
|
SetDirtyStateAction,
|
|
26
|
+
SetMarkersAction,
|
|
23
27
|
SetModelAction,
|
|
24
28
|
StartProgressAction,
|
|
25
29
|
StatusAction,
|
|
@@ -35,7 +39,6 @@ import {
|
|
|
35
39
|
type ServerModule,
|
|
36
40
|
getRequestParentName
|
|
37
41
|
} from '@eclipse-glsp/server/node.js';
|
|
38
|
-
import { ActionDispatchScope } from '@eclipse-glsp/server';
|
|
39
42
|
import { Container, ContainerModule, type interfaces } from 'inversify';
|
|
40
43
|
import type { AstNode } from '@hydranium/langium';
|
|
41
44
|
import type { ServerSharedServices } from '@hydranium/core';
|
|
@@ -87,33 +90,49 @@ export interface MakeGlspHarnessOptions {
|
|
|
87
90
|
readonly clientSessionId?: string;
|
|
88
91
|
/**
|
|
89
92
|
* Adopter-specific client action kinds to forward IN ADDITION to
|
|
90
|
-
* {@link
|
|
93
|
+
* {@link MINIMAL_CLIENT_ACTION_KINDS}. The server's
|
|
91
94
|
* `ClientActionForwarder` only forwards declared kinds to the capturing
|
|
92
95
|
* `GLSPClientProxy`, so list any custom server→client action a test needs
|
|
93
|
-
* to observe. The
|
|
96
|
+
* to observe. The minimal set covers ordinary round-trips, so most tests
|
|
94
97
|
* leave this unset.
|
|
95
98
|
*/
|
|
96
99
|
readonly additionalClientActionKinds?: ReadonlyArray<string>;
|
|
97
100
|
}
|
|
98
101
|
|
|
99
102
|
/**
|
|
100
|
-
* The
|
|
101
|
-
*
|
|
102
|
-
*
|
|
103
|
-
*
|
|
104
|
-
*
|
|
103
|
+
* The fewest client-bound action kinds a session can declare and still finish
|
|
104
|
+
* a model round-trip without the server's dispatcher erroring with "no handler
|
|
105
|
+
* registered" for an ordinary server→client action.
|
|
106
|
+
*
|
|
107
|
+
* A real GLSP client declares every kind its own handler registry holds, which
|
|
108
|
+
* is far more than this, and GLSP ships no fixed list to declare instead. So a
|
|
109
|
+
* test session that leaves one of these out sees errors no deployed client
|
|
110
|
+
* would, or none at all: a dispatch the server does not await, such as the
|
|
111
|
+
* markers after a load, fails without telling the client. The harness declares
|
|
112
|
+
* them by default; adopter-specific kinds are added via
|
|
105
113
|
* {@link MakeGlspHarnessOptions.additionalClientActionKinds}.
|
|
106
114
|
*/
|
|
107
|
-
const
|
|
115
|
+
export const MINIMAL_CLIENT_ACTION_KINDS: ReadonlyArray<string> = Object.freeze([
|
|
108
116
|
SetModelAction.KIND,
|
|
109
117
|
UpdateModelAction.KIND,
|
|
110
118
|
RequestBoundsAction.KIND,
|
|
111
119
|
SetDirtyStateAction.KIND,
|
|
112
120
|
StatusAction.KIND,
|
|
121
|
+
MessageAction.KIND,
|
|
122
|
+
SetMarkersAction.KIND,
|
|
113
123
|
StartProgressAction.KIND,
|
|
114
124
|
UpdateProgressAction.KIND,
|
|
115
125
|
EndProgressAction.KIND
|
|
116
|
-
];
|
|
126
|
+
]);
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Whether the server reported a failure to the client: a rejected request, or
|
|
130
|
+
* an ERROR or FATAL message. A server can fail a request and still send the
|
|
131
|
+
* model, so a test that sees the model has not yet seen the load succeed.
|
|
132
|
+
*/
|
|
133
|
+
export function isRejectionOrError(action: Action): boolean {
|
|
134
|
+
return RejectAction.is(action) || (MessageAction.is(action) && (action.severity === 'ERROR' || action.severity === 'FATAL'));
|
|
135
|
+
}
|
|
117
136
|
|
|
118
137
|
/** Options for {@link GlspHarness.nextModelSubmission}. */
|
|
119
138
|
export interface NextModelSubmissionOptions {
|
|
@@ -156,10 +175,11 @@ export interface GlspHarness<TState extends AbstractHydraniumGlspState<AstNode,
|
|
|
156
175
|
/** Send an action to the server as `{ clientId, action }`. Fire-and-forget (GLSP `process` is `void`). */
|
|
157
176
|
dispatch(action: Action): void;
|
|
158
177
|
/**
|
|
159
|
-
* Resolve with the next
|
|
160
|
-
*
|
|
161
|
-
*
|
|
162
|
-
*
|
|
178
|
+
* Resolve with the next action whose `kind` matches and that arrived after
|
|
179
|
+
* the last {@link dispatch}, or since {@link start} before any. One already
|
|
180
|
+
* captured and unconsumed resolves immediately, otherwise the next arrival
|
|
181
|
+
* wins. An earlier action is read from {@link actions}. Rejects after
|
|
182
|
+
* `timeoutMs` (default 2000) so a missing action fails fast.
|
|
163
183
|
*/
|
|
164
184
|
nextAction<T extends Action = Action>(kind: string, timeoutMs?: number): Promise<T>;
|
|
165
185
|
/**
|
|
@@ -179,7 +199,8 @@ export interface GlspHarness<TState extends AbstractHydraniumGlspState<AstNode,
|
|
|
179
199
|
openDocument(sourceUri: string, timeoutMs?: number): Promise<Action>;
|
|
180
200
|
/**
|
|
181
201
|
* Resolve with the next action that publishes a model — the settling point
|
|
182
|
-
* after an operation, since a successful operation re-submits.
|
|
202
|
+
* after an operation, since a successful operation re-submits. Matches as
|
|
203
|
+
* {@link nextAction} does, only after the last dispatch.
|
|
183
204
|
*
|
|
184
205
|
* Kind-agnostic for the same reason as {@link openDocument}. Set
|
|
185
206
|
* `rejectOnTimeout: false` to ask whether a submission happened *at all*.
|
|
@@ -189,6 +210,11 @@ export interface GlspHarness<TState extends AbstractHydraniumGlspState<AstNode,
|
|
|
189
210
|
* LIGHT fidelity: seed the state's source root directly via
|
|
190
211
|
* `setSourceRoot`, bypassing source-model storage. Valid only after
|
|
191
212
|
* {@link start}.
|
|
213
|
+
*
|
|
214
|
+
* A test of a provider that reads `builtNodeOf` or `referenceTo` outside
|
|
215
|
+
* an operation seeds the real state here rather than stub them. They answer as in production
|
|
216
|
+
* for a root with a `$document` in a project; without one, `referenceTo`
|
|
217
|
+
* names a target as in no project, unchecked for visibility.
|
|
192
218
|
*/
|
|
193
219
|
seedSourceRoot(uri: string, root: Parameters<TState['setSourceRoot']>[1]): void;
|
|
194
220
|
|
|
@@ -235,11 +261,13 @@ export function makeGlspHarness<TState extends AbstractHydraniumGlspState<AstNod
|
|
|
235
261
|
): GlspHarness<TState> {
|
|
236
262
|
const applicationId = options.applicationId ?? 'test-app';
|
|
237
263
|
const clientSessionId = options.clientSessionId ?? 'test-session';
|
|
238
|
-
const clientActionKinds = [...
|
|
264
|
+
const clientActionKinds = [...MINIMAL_CLIENT_ACTION_KINDS, ...(options.additionalClientActionKinds ?? [])];
|
|
239
265
|
const createLogger = options.createLogger ?? (() => makeNoopGlspLogger());
|
|
240
266
|
|
|
241
267
|
const actions: Action[] = [];
|
|
242
268
|
const consumed = new WeakSet<Action>();
|
|
269
|
+
// Where the last dispatch fell in `actions`; a wait matches only from here.
|
|
270
|
+
let dispatchedAt = 0;
|
|
243
271
|
const waiters: PendingWaiter[] = [];
|
|
244
272
|
|
|
245
273
|
const captureProxy: GLSPClientProxy = {
|
|
@@ -257,8 +285,9 @@ export function makeGlspHarness<TState extends AbstractHydraniumGlspState<AstNod
|
|
|
257
285
|
};
|
|
258
286
|
|
|
259
287
|
/**
|
|
260
|
-
* Resolve with the first unconsumed action matching any of `kinds`
|
|
261
|
-
* already captured resolves immediately, otherwise the
|
|
288
|
+
* Resolve with the first unconsumed action matching any of `kinds` since the
|
|
289
|
+
* last dispatch — one already captured resolves immediately, otherwise the
|
|
290
|
+
* next arrival wins.
|
|
262
291
|
*
|
|
263
292
|
* `rejectOnTimeout` is what lets a caller distinguish the two questions a
|
|
264
293
|
* test asks. `true` (the default) is "this must happen", and a timeout is a
|
|
@@ -268,7 +297,7 @@ export function makeGlspHarness<TState extends AbstractHydraniumGlspState<AstNod
|
|
|
268
297
|
* `ActionDispatcher.requestUntil(action, timeoutMs, rejectOnTimeout)`.
|
|
269
298
|
*/
|
|
270
299
|
function waitFor(kinds: ReadonlyArray<string>, timeoutMs: number, rejectOnTimeout: boolean): Promise<Action | undefined> {
|
|
271
|
-
const existing = actions.find(action => kinds.includes(action.kind) && !consumed.has(action));
|
|
300
|
+
const existing = actions.find((action, index) => index >= dispatchedAt && kinds.includes(action.kind) && !consumed.has(action));
|
|
272
301
|
if (existing) {
|
|
273
302
|
consumed.add(existing);
|
|
274
303
|
return Promise.resolve(existing);
|
|
@@ -290,8 +319,19 @@ export function makeGlspHarness<TState extends AbstractHydraniumGlspState<AstNod
|
|
|
290
319
|
// Distinguishing "nothing happened" from "something else
|
|
291
320
|
// happened" is the difference between a five-minute hunt and a
|
|
292
321
|
// one-line diagnosis.
|
|
293
|
-
|
|
294
|
-
|
|
322
|
+
// Split at the last dispatch, since a wait matches only what
|
|
323
|
+
// came after it: an earlier match is no answer to this one.
|
|
324
|
+
const kindsIn = (from: number, to?: number): string =>
|
|
325
|
+
actions
|
|
326
|
+
.slice(from, to)
|
|
327
|
+
.map(captured => captured.kind)
|
|
328
|
+
.join(', ') || 'nothing';
|
|
329
|
+
const context =
|
|
330
|
+
actions.length === 0
|
|
331
|
+
? 'no actions were captured at all'
|
|
332
|
+
: dispatchedAt === 0
|
|
333
|
+
? `captured since start: ${kindsIn(0)}`
|
|
334
|
+
: `captured before the last dispatch, which a wait does not match: ${kindsIn(0, dispatchedAt)}; since: ${kindsIn(dispatchedAt)}`;
|
|
295
335
|
reject(
|
|
296
336
|
new Error(
|
|
297
337
|
`makeGlspHarness: no ${kinds.map(kind => `'${kind}'`).join(' / ')} action within ${timeoutMs}ms — ${context}`
|
|
@@ -328,10 +368,10 @@ export function makeGlspHarness<TState extends AbstractHydraniumGlspState<AstNod
|
|
|
328
368
|
const container = new Container();
|
|
329
369
|
container.load(defaultAppModule, ...(options.appModules ?? []), captureProxyModule);
|
|
330
370
|
container.load(options.serverModule);
|
|
331
|
-
//
|
|
332
|
-
//
|
|
333
|
-
//
|
|
334
|
-
//
|
|
371
|
+
// Into the container the serverModule binds `GLSPServer` in, as the
|
|
372
|
+
// launchers' `configure` loads it: a harness that skipped it would keep
|
|
373
|
+
// upstream's server and answer request failures differently from every
|
|
374
|
+
// real bringup.
|
|
335
375
|
container.load(createGlspServerOverrides());
|
|
336
376
|
const server = container.get<GLSPServer>(GLSPServer);
|
|
337
377
|
|
|
@@ -378,6 +418,7 @@ export function makeGlspHarness<TState extends AbstractHydraniumGlspState<AstNod
|
|
|
378
418
|
},
|
|
379
419
|
|
|
380
420
|
dispatch(action: Action): void {
|
|
421
|
+
dispatchedAt = actions.length;
|
|
381
422
|
server.process({ clientId: clientSessionId, action });
|
|
382
423
|
},
|
|
383
424
|
|
|
@@ -389,6 +430,7 @@ export function makeGlspHarness<TState extends AbstractHydraniumGlspState<AstNod
|
|
|
389
430
|
if (!state) {
|
|
390
431
|
throw new Error('makeGlspHarness: openDocument() is only valid after start()');
|
|
391
432
|
}
|
|
433
|
+
dispatchedAt = actions.length;
|
|
392
434
|
server.process({
|
|
393
435
|
clientId: clientSessionId,
|
|
394
436
|
action: RequestModelAction.create({ options: { [SOURCE_URI_ARG]: sourceUri } })
|
|
@@ -7,10 +7,10 @@
|
|
|
7
7
|
* SPDX-License-Identifier: MIT
|
|
8
8
|
********************************************************************************/
|
|
9
9
|
|
|
10
|
-
import { type Marker, MarkerKind } from '@eclipse-glsp/
|
|
10
|
+
import { type Marker, MarkerKind } from '@eclipse-glsp/server';
|
|
11
11
|
import { type AstNode } from '@hydranium/langium';
|
|
12
12
|
import { Diagnostic, DiagnosticSeverity } from 'vscode-languageserver-types';
|
|
13
|
-
import { type
|
|
13
|
+
import { type AstDiagnostic } from '@hydranium/core';
|
|
14
14
|
|
|
15
15
|
/**
|
|
16
16
|
* The model-shaped lookups the diagnostic→marker translation needs, injected so
|
|
@@ -48,7 +48,7 @@ export interface DiagnosticMarkerLookups {
|
|
|
48
48
|
* `MarkersReason` so a fresh `SetMarkersAction` replaces the previous markers
|
|
49
49
|
* (an empty result clears them when all errors are fixed).
|
|
50
50
|
*/
|
|
51
|
-
export function diagnosticsToMarkers(diagnostics: readonly
|
|
51
|
+
export function diagnosticsToMarkers(diagnostics: readonly AstDiagnostic[], lookups: DiagnosticMarkerLookups): Marker[] {
|
|
52
52
|
const markers: Marker[] = [];
|
|
53
53
|
for (const diagnostic of diagnostics) {
|
|
54
54
|
const kind = markerKind(diagnostic.severity);
|
|
@@ -7,12 +7,11 @@
|
|
|
7
7
|
* SPDX-License-Identifier: MIT
|
|
8
8
|
********************************************************************************/
|
|
9
9
|
|
|
10
|
-
import { type Marker } from '@eclipse-glsp/
|
|
11
|
-
import { type GModelElement, ModelState, type ModelValidator } from '@eclipse-glsp/server';
|
|
10
|
+
import { type GModelElement, type Marker, ModelState, type ModelValidator } from '@eclipse-glsp/server';
|
|
12
11
|
import { inject, injectable } from 'inversify';
|
|
13
12
|
import { type AstNode } from '@hydranium/langium';
|
|
14
13
|
import { URI } from '@hydranium/langium';
|
|
15
|
-
import { type ServerSharedServices, type
|
|
14
|
+
import { type ServerSharedServices, type AstDiagnostic } from '@hydranium/core';
|
|
16
15
|
import { type AbstractHydraniumGlspState } from '../state/abstract-hydranium-glsp-state.js';
|
|
17
16
|
import { HydraniumTypes } from '../state/hydranium-shared-core-services.js';
|
|
18
17
|
import { type DiagnosticMarkerLookups, diagnosticsToMarkers } from './diagnostic-markers.js';
|
|
@@ -75,9 +74,9 @@ export class HydraniumGlspModelValidator<TRoot extends AstNode = AstNode> implem
|
|
|
75
74
|
continue;
|
|
76
75
|
}
|
|
77
76
|
// Diagnostics are produced by the framework's `HydraniumDocumentValidator`,
|
|
78
|
-
// which emits `
|
|
77
|
+
// which emits `AstDiagnostic` (LSP `Diagnostic` + `element` path).
|
|
79
78
|
// Parser/lexer diagnostics carry no `element`; the lookup drops them.
|
|
80
|
-
const diagnostics = document.diagnostics as
|
|
79
|
+
const diagnostics = document.diagnostics as AstDiagnostic[] | undefined;
|
|
81
80
|
if (!diagnostics || diagnostics.length === 0) {
|
|
82
81
|
continue;
|
|
83
82
|
}
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
/********************************************************************************
|
|
2
|
-
* Copyright (c) 2026 CrossBreeze, EclipseSource and others.
|
|
3
|
-
*
|
|
4
|
-
* This program and the accompanying materials are made available under the
|
|
5
|
-
* terms of the MIT License which is available in the project root.
|
|
6
|
-
*
|
|
7
|
-
* SPDX-License-Identifier: MIT
|
|
8
|
-
********************************************************************************/
|
|
9
|
-
/**
|
|
10
|
-
* How `HydraniumGlspStorage.saveSourceModel` reacts when a concurrent edit has
|
|
11
|
-
* advanced the document past the version this diagram was last captured at.
|
|
12
|
-
*
|
|
13
|
-
* A save spans otherwise-independent choices — whether to guard on the captured
|
|
14
|
-
* based-on version, whether the GLSP save action awaits the persist, and what
|
|
15
|
-
* happens on failure. Each arm bundles those into one coherent, nameable policy
|
|
16
|
-
* so an adopter selects a whole behaviour rather than assembling an incoherent
|
|
17
|
-
* mix: fire-and-forget plus rethrow would leave an unhandled rejection. It is a
|
|
18
|
-
* *selection of configuration*, delivered as a bound option (see the
|
|
19
|
-
* {@link SaveConflictPolicy} symbol) rather than a behaviour hook.
|
|
20
|
-
*/
|
|
21
|
-
export type SaveConflictPolicy =
|
|
22
|
-
/**
|
|
23
|
-
* Last-write-wins: no based-on guard, await the persist, propagate any
|
|
24
|
-
* failure to the GLSP save action. The default; correct for a single-editor
|
|
25
|
-
* head where nothing races the save.
|
|
26
|
-
*/
|
|
27
|
-
{
|
|
28
|
-
kind: 'overwrite';
|
|
29
|
-
}
|
|
30
|
-
/**
|
|
31
|
-
* Guard on the captured version, await the persist, and surface a
|
|
32
|
-
* `ConflictError` (and any other failure) to the GLSP save action.
|
|
33
|
-
*/
|
|
34
|
-
| {
|
|
35
|
-
kind: 'reject';
|
|
36
|
-
}
|
|
37
|
-
/**
|
|
38
|
-
* Guard on the captured version, fire-and-forget, and log + swallow every
|
|
39
|
-
* failure. Correct when another editor of the same document may already have
|
|
40
|
-
* written the truth, so a stale diagram save is benign and must neither
|
|
41
|
-
* block the action nor surface as an error.
|
|
42
|
-
*/
|
|
43
|
-
| {
|
|
44
|
-
kind: 'drop-and-log';
|
|
45
|
-
};
|
|
46
|
-
/** The policy applied when no {@link SaveConflictPolicy} option is bound. */
|
|
47
|
-
export declare const DEFAULT_SAVE_CONFLICT_POLICY: SaveConflictPolicy;
|
|
48
|
-
/**
|
|
49
|
-
* DI token for the {@link SaveConflictPolicy} option. Bind a constant value in a
|
|
50
|
-
* `DiagramModule` to select a non-default policy; left unbound,
|
|
51
|
-
* `HydraniumGlspStorage` falls back to
|
|
52
|
-
* {@link DEFAULT_SAVE_CONFLICT_POLICY}. Shares its name with the type, the way a
|
|
53
|
-
* `class` is both a value and a type.
|
|
54
|
-
*/
|
|
55
|
-
export declare const SaveConflictPolicy: unique symbol;
|
|
56
|
-
//# sourceMappingURL=save-conflict-policy.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"save-conflict-policy.d.ts","sourceRoot":"","sources":["../../src/storage/save-conflict-policy.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAElF;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,kBAAkB;AAC3B;;;;GAIG;AACD;IAAE,IAAI,EAAE,WAAW,CAAA;CAAE;AACvB;;;GAGG;GACD;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE;AACpB;;;;;GAKG;GACD;IAAE,IAAI,EAAE,cAAc,CAAA;CAAE,CAAC;AAE9B,6EAA6E;AAC7E,eAAO,MAAM,4BAA4B,EAAE,kBAA0C,CAAC;AAEtF;;;;;;GAMG;AACH,eAAO,MAAM,kBAAkB,eAA+B,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"save-conflict-policy.js","sourceRoot":"","sources":["../../src/storage/save-conflict-policy.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAkClF,6EAA6E;AAC7E,MAAM,CAAC,MAAM,4BAA4B,GAAuB,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC;AAEtF;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,MAAM,CAAC,oBAAoB,CAAC,CAAC"}
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
/********************************************************************************
|
|
2
|
-
* Copyright (c) 2026 CrossBreeze, EclipseSource and others.
|
|
3
|
-
*
|
|
4
|
-
* This program and the accompanying materials are made available under the
|
|
5
|
-
* terms of the MIT License which is available in the project root.
|
|
6
|
-
*
|
|
7
|
-
* SPDX-License-Identifier: MIT
|
|
8
|
-
********************************************************************************/
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* How `HydraniumGlspStorage.saveSourceModel` reacts when a concurrent edit has
|
|
12
|
-
* advanced the document past the version this diagram was last captured at.
|
|
13
|
-
*
|
|
14
|
-
* A save spans otherwise-independent choices — whether to guard on the captured
|
|
15
|
-
* based-on version, whether the GLSP save action awaits the persist, and what
|
|
16
|
-
* happens on failure. Each arm bundles those into one coherent, nameable policy
|
|
17
|
-
* so an adopter selects a whole behaviour rather than assembling an incoherent
|
|
18
|
-
* mix: fire-and-forget plus rethrow would leave an unhandled rejection. It is a
|
|
19
|
-
* *selection of configuration*, delivered as a bound option (see the
|
|
20
|
-
* {@link SaveConflictPolicy} symbol) rather than a behaviour hook.
|
|
21
|
-
*/
|
|
22
|
-
export type SaveConflictPolicy =
|
|
23
|
-
/**
|
|
24
|
-
* Last-write-wins: no based-on guard, await the persist, propagate any
|
|
25
|
-
* failure to the GLSP save action. The default; correct for a single-editor
|
|
26
|
-
* head where nothing races the save.
|
|
27
|
-
*/
|
|
28
|
-
| { kind: 'overwrite' }
|
|
29
|
-
/**
|
|
30
|
-
* Guard on the captured version, await the persist, and surface a
|
|
31
|
-
* `ConflictError` (and any other failure) to the GLSP save action.
|
|
32
|
-
*/
|
|
33
|
-
| { kind: 'reject' }
|
|
34
|
-
/**
|
|
35
|
-
* Guard on the captured version, fire-and-forget, and log + swallow every
|
|
36
|
-
* failure. Correct when another editor of the same document may already have
|
|
37
|
-
* written the truth, so a stale diagram save is benign and must neither
|
|
38
|
-
* block the action nor surface as an error.
|
|
39
|
-
*/
|
|
40
|
-
| { kind: 'drop-and-log' };
|
|
41
|
-
|
|
42
|
-
/** The policy applied when no {@link SaveConflictPolicy} option is bound. */
|
|
43
|
-
export const DEFAULT_SAVE_CONFLICT_POLICY: SaveConflictPolicy = { kind: 'overwrite' };
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* DI token for the {@link SaveConflictPolicy} option. Bind a constant value in a
|
|
47
|
-
* `DiagramModule` to select a non-default policy; left unbound,
|
|
48
|
-
* `HydraniumGlspStorage` falls back to
|
|
49
|
-
* {@link DEFAULT_SAVE_CONFLICT_POLICY}. Shares its name with the type, the way a
|
|
50
|
-
* `class` is both a value and a type.
|
|
51
|
-
*/
|
|
52
|
-
export const SaveConflictPolicy = Symbol('SaveConflictPolicy');
|