@hydranium/glsp-server 1.0.0-next.117 → 1.0.0-next.123
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/lib/command/hydranium-glsp-recording-command.d.ts +1 -1
- package/lib/command/hydranium-glsp-recording-command.js +1 -1
- package/lib/messages/index.d.ts +1 -1
- package/lib/messages/index.d.ts.map +1 -1
- package/lib/messages/index.js +1 -1
- package/lib/messages/index.js.map +1 -1
- package/lib/state/abstract-hydranium-glsp-state.d.ts +52 -8
- package/lib/state/abstract-hydranium-glsp-state.d.ts.map +1 -1
- package/lib/state/abstract-hydranium-glsp-state.js +77 -5
- package/lib/state/abstract-hydranium-glsp-state.js.map +1 -1
- package/lib/state/full-text-hydranium-glsp-state.d.ts +4 -4
- package/lib/state/full-text-hydranium-glsp-state.d.ts.map +1 -1
- package/lib/state/full-text-hydranium-glsp-state.js +5 -10
- package/lib/state/full-text-hydranium-glsp-state.js.map +1 -1
- package/lib/state/reconcile-source-model-write.d.ts +2 -2
- package/lib/state/reconcile-source-model-write.d.ts.map +1 -1
- package/lib/state/reconcile-source-model-write.js +1 -1
- package/lib/state/reconcile-source-model-write.js.map +1 -1
- package/lib/state/reconciling-multi-document-glsp-state.d.ts +54 -74
- package/lib/state/reconciling-multi-document-glsp-state.d.ts.map +1 -1
- package/lib/state/reconciling-multi-document-glsp-state.js +77 -102
- package/lib/state/reconciling-multi-document-glsp-state.js.map +1 -1
- package/lib/state/reconciling-transfer-hydranium-glsp-state.d.ts +16 -15
- package/lib/state/reconciling-transfer-hydranium-glsp-state.d.ts.map +1 -1
- package/lib/state/reconciling-transfer-hydranium-glsp-state.js +21 -25
- package/lib/state/reconciling-transfer-hydranium-glsp-state.js.map +1 -1
- package/lib/storage/hydranium-glsp-storage.d.ts +103 -26
- package/lib/storage/hydranium-glsp-storage.d.ts.map +1 -1
- package/lib/storage/hydranium-glsp-storage.js +199 -32
- package/lib/storage/hydranium-glsp-storage.js.map +1 -1
- package/package.json +7 -7
- package/src/command/hydranium-glsp-recording-command.ts +1 -1
- package/src/messages/index.ts +6 -1
- package/src/state/abstract-hydranium-glsp-state.ts +85 -8
- package/src/state/full-text-hydranium-glsp-state.ts +5 -10
- package/src/state/reconcile-source-model-write.ts +3 -3
- package/src/state/reconciling-multi-document-glsp-state.ts +78 -103
- package/src/state/reconciling-transfer-hydranium-glsp-state.ts +21 -25
- package/src/storage/hydranium-glsp-storage.ts +236 -33
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
********************************************************************************/
|
|
9
9
|
import { type JsonModelState } from '@eclipse-glsp/server';
|
|
10
10
|
import { type AstNode } from '@hydranium/langium';
|
|
11
|
+
import { type ClientSession } from '@hydranium/core';
|
|
11
12
|
import { type BasedOn, type TransferElement } from '@hydranium/protocol';
|
|
12
13
|
import { AbstractHydraniumGlspState } from './abstract-hydranium-glsp-state.js';
|
|
13
14
|
/**
|
|
@@ -39,44 +40,30 @@ export interface MultiDocumentSourceModel<TPrimary extends TransferElement = Tra
|
|
|
39
40
|
* defines them over the primary plus the secondary write set registered through
|
|
40
41
|
* {@link AbstractHydraniumGlspState.trackSecondaryDocument}.
|
|
41
42
|
*
|
|
42
|
-
* **
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
* back, and the document store commits per URI. An adopter that cannot accept the
|
|
47
|
-
* window should not span documents in one operation.
|
|
43
|
+
* **The write set is written all or none.** {@link persist} hands every
|
|
44
|
+
* changed document to one `ClientSession.updateAll` on the diagram's session,
|
|
45
|
+
* so a conflict on any document leaves every document of the set as it was,
|
|
46
|
+
* and write order carries no meaning.
|
|
48
47
|
*
|
|
49
|
-
* **
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
* secondaries-then-primary, which is correct for the common shape where the
|
|
56
|
-
* primary is the DIAGRAM and the semantics it references are secondaries: the
|
|
57
|
-
* user opened the diagram, so it is also the document the conflict gate should
|
|
58
|
-
* guard. **An adopter whose primary is the referenced document — a semantic file
|
|
59
|
-
* as the diagram source, with layout in a secondary — has the ordering backwards
|
|
60
|
-
* and must override {@link persist} to write the primary first.** Overriding it
|
|
61
|
-
* is the supported route; the base order is a default for the common case, not an
|
|
62
|
-
* invariant of the class.
|
|
48
|
+
* **Every document of the set is gated.** The primary on the caller's
|
|
49
|
+
* `basedOn`, each secondary on {@link secondaryBasedOn}, by default the version
|
|
50
|
+
* it had when the source root was last read. A conflict on any of them is
|
|
51
|
+
* reconciled against the whole write set. A write based on `'anything'` — a
|
|
52
|
+
* merged retry, an undo or redo replaying a patch — forces every document of
|
|
53
|
+
* the set.
|
|
63
54
|
*
|
|
64
|
-
*
|
|
65
|
-
*
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
* merged one — the atomicity problem again, one layer up. An adopter that wants
|
|
69
|
-
* a coarser check overrides {@link secondaryBasedOn} to return the version
|
|
70
|
-
* {@link AbstractHydraniumGlspState.snapshotVersionOf} already holds, and takes
|
|
71
|
-
* on the partial-write window named there.
|
|
55
|
+
* A secondary is written only while the diagram's session has it open. The
|
|
56
|
+
* storage opens it as it joins the write set, and {@link openForWrite} opens it
|
|
57
|
+
* again before each write; an adopter whose write set can name a document that
|
|
58
|
+
* does not exist yet overrides {@link openForWrite} to create it.
|
|
72
59
|
*/
|
|
73
60
|
export declare class ReconcilingMultiDocumentGlspState<TRoot extends AstNode, TPrimary extends TransferElement = TransferElement> extends AbstractHydraniumGlspState<TRoot, MultiDocumentSourceModel<TPrimary>> implements JsonModelState<MultiDocumentSourceModel<TPrimary>> {
|
|
74
61
|
/**
|
|
75
62
|
* Last in-sync projection across the whole write set, captured on every
|
|
76
|
-
* {@link setSourceRoot}. Same role as the single-document
|
|
63
|
+
* {@link setSourceRoot}. Same role as the single-document base: the state a
|
|
77
64
|
* forward-write conflict reconciles the user's intent against.
|
|
78
65
|
*/
|
|
79
|
-
protected
|
|
66
|
+
protected base?: MultiDocumentSourceModel<TPrimary>;
|
|
80
67
|
/**
|
|
81
68
|
* Projection of the primary plus every registered secondary, in the framework
|
|
82
69
|
* encoder's `'grammar'` mode (authored state only — cross-references as
|
|
@@ -94,14 +81,14 @@ export declare class ReconcilingMultiDocumentGlspState<TRoot extends AstNode, TP
|
|
|
94
81
|
* Register the secondary documents that belong to the primary at `uri`, via
|
|
95
82
|
* {@link AbstractHydraniumGlspState.trackSecondaryDocument}. Called on every
|
|
96
83
|
* {@link setSourceRoot}, after the primary is captured (so `sourceUri` is
|
|
97
|
-
* current) and BEFORE the
|
|
84
|
+
* current) and BEFORE the base is taken (so the base includes them).
|
|
98
85
|
* Default: no secondaries.
|
|
99
86
|
*
|
|
100
87
|
* This hook exists because that ordering is a trap an adopter would otherwise
|
|
101
88
|
* hit silently. Registering from an overridden `setSourceRoot` *after*
|
|
102
|
-
* `super.setSourceRoot(...)` runs too late — the
|
|
89
|
+
* `super.setSourceRoot(...)` runs too late — the base has already been
|
|
103
90
|
* captured without the secondaries, so the first conflict reconcile measures
|
|
104
|
-
* the user's intent against a
|
|
91
|
+
* the user's intent against a base missing half the write set and the
|
|
105
92
|
* secondary edits look like foreign changes. Registering *before* the super
|
|
106
93
|
* call is too early for a URI derived from the new primary. Overriding this
|
|
107
94
|
* instead removes the choice.
|
|
@@ -109,68 +96,61 @@ export declare class ReconcilingMultiDocumentGlspState<TRoot extends AstNode, TP
|
|
|
109
96
|
protected trackWriteSet(_uri: string): void;
|
|
110
97
|
/**
|
|
111
98
|
* Persist the whole write set, then capture the resulting primary root. On a
|
|
112
|
-
* `ConflictError` from the
|
|
113
|
-
* as the single-document state does — the orchestration is
|
|
99
|
+
* `ConflictError` from any document of the set, reconcile via the injected
|
|
100
|
+
* policy exactly as the single-document state does — the orchestration is
|
|
101
|
+
* shared.
|
|
114
102
|
*/
|
|
115
103
|
updateSourceModel(model: MultiDocumentSourceModel<TPrimary>, basedOn?: BasedOn): Promise<void>;
|
|
116
104
|
/**
|
|
117
|
-
* Write hook —
|
|
118
|
-
*
|
|
119
|
-
*
|
|
120
|
-
*
|
|
105
|
+
* Write hook — every document of `model` that changed, opened first through
|
|
106
|
+
* {@link openForWrite}, in one `updateAll` on the diagram's session: the
|
|
107
|
+
* primary gated on `basedOn`, each secondary on {@link secondaryBasedOn}, or
|
|
108
|
+
* every document on `'anything'` when `basedOn` is `'anything'`. Resolves to
|
|
109
|
+
* the primary's root, the one already captured when the primary did not
|
|
110
|
+
* change. A write that bypasses `updateAll` gives up the all-or-none
|
|
111
|
+
* guarantee the class describes. Throws without a session
|
|
112
|
+
* ({@link requireModelSession}).
|
|
121
113
|
*/
|
|
122
114
|
protected persist(model: MultiDocumentSourceModel<TPrimary>, basedOn: BasedOn): Promise<{
|
|
123
115
|
root: TRoot;
|
|
124
116
|
}>;
|
|
125
117
|
/**
|
|
126
|
-
* Whether `candidate` differs from the
|
|
118
|
+
* Whether `candidate` differs from the base projection of the same
|
|
127
119
|
* document, and therefore needs writing.
|
|
128
120
|
*
|
|
129
121
|
* **Skipping unchanged documents is correctness, not an optimisation.** A
|
|
130
|
-
* write
|
|
131
|
-
*
|
|
132
|
-
*
|
|
133
|
-
*
|
|
134
|
-
*
|
|
135
|
-
*
|
|
122
|
+
* write re-serializes from the AST, so writing a document that did not
|
|
123
|
+
* change still rewrites its text in the serializer's own layout. Persisting
|
|
124
|
+
* the whole write set unconditionally therefore means a pure layout drag
|
|
125
|
+
* reflows the semantic file, a change the user never asked for and would
|
|
126
|
+
* struggle to attribute. Comments survive that rewrite, but the
|
|
127
|
+
* hand-formatting around them does not.
|
|
136
128
|
*
|
|
137
129
|
* Compared by serialised form. Both sides come from the same encoder walking
|
|
138
130
|
* the same shape, so key order is stable and a string compare is sound here;
|
|
139
131
|
* it is also cheap enough to run per document per write.
|
|
140
132
|
*/
|
|
141
|
-
protected hasChanged(
|
|
142
|
-
/** Write the primary document, opting into the conflict gate unless `basedOn` is `'anything'`. */
|
|
143
|
-
protected persistPrimary(model: TPrimary, basedOn: BasedOn): Promise<{
|
|
144
|
-
root: TRoot;
|
|
145
|
-
}>;
|
|
133
|
+
protected hasChanged(base: object | undefined, candidate: object): boolean;
|
|
146
134
|
/**
|
|
147
|
-
*
|
|
148
|
-
*
|
|
149
|
-
*
|
|
150
|
-
*
|
|
135
|
+
* Make sure the diagram's session has `uri` open before the write set is
|
|
136
|
+
* written. Default: open it, a no-op for a document the session already
|
|
137
|
+
* has open. Override to create a document the write set names before it
|
|
138
|
+
* exists, through `session.create`: `updateAll` opens nothing.
|
|
151
139
|
*/
|
|
152
|
-
protected
|
|
140
|
+
protected openForWrite(session: ClientSession<AstNode>, uri: string): Promise<void>;
|
|
153
141
|
/**
|
|
154
|
-
* What a secondary write declares it was based on. Default
|
|
155
|
-
*
|
|
156
|
-
*
|
|
157
|
-
*
|
|
158
|
-
*
|
|
159
|
-
*
|
|
160
|
-
* ({@link AbstractHydraniumGlspState.snapshotVersionOf}), and returning that
|
|
161
|
-
* value here is the whole opt-in; without it the only place to put the
|
|
162
|
-
* comparison is a copy of {@link persistSecondary}, which then has to be kept
|
|
163
|
-
* in step with the framework's write call.
|
|
164
|
-
*
|
|
165
|
-
* **Opting in buys a conflict report and costs atomicity.** A gated secondary
|
|
166
|
-
* throws mid-set, after earlier secondaries have already been written, and if
|
|
167
|
-
* the reconcile then drops the edit those writes stay. Weigh that against the
|
|
168
|
-
* default, which lets a foreign edit to a secondary be overwritten silently.
|
|
142
|
+
* What a secondary write declares it was based on. Default: the version the
|
|
143
|
+
* secondary had when the source root was last read
|
|
144
|
+
* ({@link AbstractHydraniumGlspState.snapshotVersionOf}), so a foreign edit
|
|
145
|
+
* to it since is reported as a conflict and reconciled rather than
|
|
146
|
+
* overwritten; `'anything'` for a secondary with no recorded version.
|
|
147
|
+
* Return `'anything'` to force secondary writes.
|
|
169
148
|
*/
|
|
170
|
-
protected secondaryBasedOn(
|
|
149
|
+
protected secondaryBasedOn(uri: string): BasedOn;
|
|
171
150
|
/**
|
|
172
|
-
* Refetch hook — the current
|
|
173
|
-
*
|
|
151
|
+
* Refetch hook — the current projection across the write set, each document
|
|
152
|
+
* read through {@link AbstractHydraniumGlspState.readCurrentRoot}: theirs,
|
|
153
|
+
* which the conflict resolver replays the user's intent onto.
|
|
174
154
|
* Returns `undefined` when the PRIMARY cannot be read, since a reconcile
|
|
175
155
|
* without it has nothing to merge into; an unreadable secondary is omitted the
|
|
176
156
|
* same way {@link sourceModel} omits one.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reconciling-multi-document-glsp-state.d.ts","sourceRoot":"","sources":["../../src/state/reconciling-multi-document-glsp-state.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAElF,OAAO,EAAE,KAAK,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAE3D,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,KAAK,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACzE,OAAO,EAAE,0BAA0B,EAAE,MAAM,oCAAoC,CAAC;AAGhF;;;;;;;;;GASG;AACH,MAAM,WAAW,wBAAwB,CAAC,QAAQ,SAAS,eAAe,GAAG,eAAe;IACzF,gFAAgF;IAChF,OAAO,EAAE,QAAQ,CAAC;IAClB,0EAA0E;IAC1E,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;CAC/C;AAED
|
|
1
|
+
{"version":3,"file":"reconciling-multi-document-glsp-state.d.ts","sourceRoot":"","sources":["../../src/state/reconciling-multi-document-glsp-state.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAElF,OAAO,EAAE,KAAK,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAE3D,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,KAAK,aAAa,EAA+B,MAAM,iBAAiB,CAAC;AAClF,OAAO,EAAE,KAAK,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACzE,OAAO,EAAE,0BAA0B,EAAE,MAAM,oCAAoC,CAAC;AAGhF;;;;;;;;;GASG;AACH,MAAM,WAAW,wBAAwB,CAAC,QAAQ,SAAS,eAAe,GAAG,eAAe;IACzF,gFAAgF;IAChF,OAAO,EAAE,QAAQ,CAAC;IAClB,0EAA0E;IAC1E,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;CAC/C;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,qBACa,iCAAiC,CAAC,KAAK,SAAS,OAAO,EAAE,QAAQ,SAAS,eAAe,GAAG,eAAe,CACrH,SAAQ,0BAA0B,CAAC,KAAK,EAAE,wBAAwB,CAAC,QAAQ,CAAC,CAC5E,YAAW,cAAc,CAAC,wBAAwB,CAAC,QAAQ,CAAC,CAAC;IAE7D;;;;OAIG;IACH,SAAS,CAAC,IAAI,CAAC,EAAE,wBAAwB,CAAC,QAAQ,CAAC,CAAC;IAEpD;;;;;;;;;;OAUG;IACH,IAAI,WAAW,IAAI,wBAAwB,CAAC,QAAQ,CAAC,CASpD;IAEQ,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,GAAG,IAAI;IAMtD;;;;;;;;;;;;;;;OAeG;IACH,SAAS,CAAC,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAI3C;;;;;OAKG;IACG,iBAAiB,CAAC,KAAK,EAAE,wBAAwB,CAAC,QAAQ,CAAC,EAAE,OAAO,GAAE,OAAsB,GAAG,OAAO,CAAC,IAAI,CAAC;IAclH;;;;;;;;;OASG;cACa,OAAO,CAAC,KAAK,EAAE,wBAAwB,CAAC,QAAQ,CAAC,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC;QAAE,IAAI,EAAE,KAAK,CAAA;KAAE,CAAC;IAqB9G;;;;;;;;;;;;;;;OAeG;IACH,SAAS,CAAC,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO;IAI1E;;;;;OAKG;IACH,SAAS,CAAC,YAAY,CAAC,OAAO,EAAE,aAAa,CAAC,OAAO,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAInF;;;;;;;OAOG;IACH,SAAS,CAAC,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAIhD;;;;;;;OAOG;cACa,OAAO,IAAI,OAAO,CAAC,wBAAwB,CAAC,QAAQ,CAAC,GAAG,SAAS,CAAC;IAelF,wFAAwF;IACxF,SAAS,CAAC,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS;IAKnE,oFAAoF;IACpF,SAAS,CAAC,WAAW,CAAC,CAAC,SAAS,eAAe,GAAG,eAAe,EAAE,IAAI,EAAE,OAAO,GAAG,CAAC;CAGtF"}
|
|
@@ -28,44 +28,30 @@ import { reconcileSourceModelWrite } from './reconcile-source-model-write.js';
|
|
|
28
28
|
* defines them over the primary plus the secondary write set registered through
|
|
29
29
|
* {@link AbstractHydraniumGlspState.trackSecondaryDocument}.
|
|
30
30
|
*
|
|
31
|
-
* **
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
* back, and the document store commits per URI. An adopter that cannot accept the
|
|
36
|
-
* window should not span documents in one operation.
|
|
31
|
+
* **The write set is written all or none.** {@link persist} hands every
|
|
32
|
+
* changed document to one `ClientSession.updateAll` on the diagram's session,
|
|
33
|
+
* so a conflict on any document leaves every document of the set as it was,
|
|
34
|
+
* and write order carries no meaning.
|
|
37
35
|
*
|
|
38
|
-
* **
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
* secondaries-then-primary, which is correct for the common shape where the
|
|
45
|
-
* primary is the DIAGRAM and the semantics it references are secondaries: the
|
|
46
|
-
* user opened the diagram, so it is also the document the conflict gate should
|
|
47
|
-
* guard. **An adopter whose primary is the referenced document — a semantic file
|
|
48
|
-
* as the diagram source, with layout in a secondary — has the ordering backwards
|
|
49
|
-
* and must override {@link persist} to write the primary first.** Overriding it
|
|
50
|
-
* is the supported route; the base order is a default for the common case, not an
|
|
51
|
-
* invariant of the class.
|
|
36
|
+
* **Every document of the set is gated.** The primary on the caller's
|
|
37
|
+
* `basedOn`, each secondary on {@link secondaryBasedOn}, by default the version
|
|
38
|
+
* it had when the source root was last read. A conflict on any of them is
|
|
39
|
+
* reconciled against the whole write set. A write based on `'anything'` — a
|
|
40
|
+
* merged retry, an undo or redo replaying a patch — forces every document of
|
|
41
|
+
* the set.
|
|
52
42
|
*
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
* merged one — the atomicity problem again, one layer up. An adopter that wants
|
|
58
|
-
* a coarser check overrides {@link secondaryBasedOn} to return the version
|
|
59
|
-
* {@link AbstractHydraniumGlspState.snapshotVersionOf} already holds, and takes
|
|
60
|
-
* on the partial-write window named there.
|
|
43
|
+
* A secondary is written only while the diagram's session has it open. The
|
|
44
|
+
* storage opens it as it joins the write set, and {@link openForWrite} opens it
|
|
45
|
+
* again before each write; an adopter whose write set can name a document that
|
|
46
|
+
* does not exist yet overrides {@link openForWrite} to create it.
|
|
61
47
|
*/
|
|
62
48
|
let ReconcilingMultiDocumentGlspState = class ReconcilingMultiDocumentGlspState extends AbstractHydraniumGlspState {
|
|
63
49
|
/**
|
|
64
50
|
* Last in-sync projection across the whole write set, captured on every
|
|
65
|
-
* {@link setSourceRoot}. Same role as the single-document
|
|
51
|
+
* {@link setSourceRoot}. Same role as the single-document base: the state a
|
|
66
52
|
* forward-write conflict reconciles the user's intent against.
|
|
67
53
|
*/
|
|
68
|
-
|
|
54
|
+
base;
|
|
69
55
|
/**
|
|
70
56
|
* Projection of the primary plus every registered secondary, in the framework
|
|
71
57
|
* encoder's `'grammar'` mode (authored state only — cross-references as
|
|
@@ -90,20 +76,20 @@ let ReconcilingMultiDocumentGlspState = class ReconcilingMultiDocumentGlspState
|
|
|
90
76
|
setSourceRoot(uri, root) {
|
|
91
77
|
super.setSourceRoot(uri, root);
|
|
92
78
|
this.trackWriteSet(uri);
|
|
93
|
-
this.
|
|
79
|
+
this.base = this.sourceModel;
|
|
94
80
|
}
|
|
95
81
|
/**
|
|
96
82
|
* Register the secondary documents that belong to the primary at `uri`, via
|
|
97
83
|
* {@link AbstractHydraniumGlspState.trackSecondaryDocument}. Called on every
|
|
98
84
|
* {@link setSourceRoot}, after the primary is captured (so `sourceUri` is
|
|
99
|
-
* current) and BEFORE the
|
|
85
|
+
* current) and BEFORE the base is taken (so the base includes them).
|
|
100
86
|
* Default: no secondaries.
|
|
101
87
|
*
|
|
102
88
|
* This hook exists because that ordering is a trap an adopter would otherwise
|
|
103
89
|
* hit silently. Registering from an overridden `setSourceRoot` *after*
|
|
104
|
-
* `super.setSourceRoot(...)` runs too late — the
|
|
90
|
+
* `super.setSourceRoot(...)` runs too late — the base has already been
|
|
105
91
|
* captured without the secondaries, so the first conflict reconcile measures
|
|
106
|
-
* the user's intent against a
|
|
92
|
+
* the user's intent against a base missing half the write set and the
|
|
107
93
|
* secondary edits look like foreign changes. Registering *before* the super
|
|
108
94
|
* call is too early for a URI derived from the new primary. Overriding this
|
|
109
95
|
* instead removes the choice.
|
|
@@ -113,8 +99,9 @@ let ReconcilingMultiDocumentGlspState = class ReconcilingMultiDocumentGlspState
|
|
|
113
99
|
}
|
|
114
100
|
/**
|
|
115
101
|
* Persist the whole write set, then capture the resulting primary root. On a
|
|
116
|
-
* `ConflictError` from the
|
|
117
|
-
* as the single-document state does — the orchestration is
|
|
102
|
+
* `ConflictError` from any document of the set, reconcile via the injected
|
|
103
|
+
* policy exactly as the single-document state does — the orchestration is
|
|
104
|
+
* shared.
|
|
118
105
|
*/
|
|
119
106
|
async updateSourceModel(model, basedOn = this.basedOn) {
|
|
120
107
|
return reconcileSourceModelWrite(model, basedOn, {
|
|
@@ -123,114 +110,102 @@ let ReconcilingMultiDocumentGlspState = class ReconcilingMultiDocumentGlspState
|
|
|
123
110
|
this.setSourceRoot(this._sourceUri, root);
|
|
124
111
|
},
|
|
125
112
|
refetch: () => this.refetch(),
|
|
126
|
-
|
|
113
|
+
base: this.base,
|
|
127
114
|
conflictResolver: this.conflictResolver,
|
|
128
115
|
logger: this.logger,
|
|
129
116
|
onConflictDropped: () => this.refreshSourceRoot()
|
|
130
117
|
});
|
|
131
118
|
}
|
|
132
119
|
/**
|
|
133
|
-
* Write hook —
|
|
134
|
-
*
|
|
135
|
-
*
|
|
136
|
-
*
|
|
120
|
+
* Write hook — every document of `model` that changed, opened first through
|
|
121
|
+
* {@link openForWrite}, in one `updateAll` on the diagram's session: the
|
|
122
|
+
* primary gated on `basedOn`, each secondary on {@link secondaryBasedOn}, or
|
|
123
|
+
* every document on `'anything'` when `basedOn` is `'anything'`. Resolves to
|
|
124
|
+
* the primary's root, the one already captured when the primary did not
|
|
125
|
+
* change. A write that bypasses `updateAll` gives up the all-or-none
|
|
126
|
+
* guarantee the class describes. Throws without a session
|
|
127
|
+
* ({@link requireModelSession}).
|
|
137
128
|
*/
|
|
138
129
|
async persist(model, basedOn) {
|
|
130
|
+
const primaryChanged = this.hasChanged(this.base?.primary, model.primary);
|
|
131
|
+
const updates = primaryChanged
|
|
132
|
+
? [{ uri: this._sourceUri, model: model.primary, basedOn }]
|
|
133
|
+
: [];
|
|
139
134
|
for (const [uri, secondary] of Object.entries(model.secondaries)) {
|
|
140
|
-
if (this.hasChanged(this.
|
|
141
|
-
|
|
135
|
+
if (this.hasChanged(this.base?.secondaries[uri], secondary)) {
|
|
136
|
+
updates.push({ uri, model: secondary, basedOn: basedOn === 'anything' ? 'anything' : this.secondaryBasedOn(uri) });
|
|
142
137
|
}
|
|
143
138
|
}
|
|
144
|
-
if (
|
|
145
|
-
// Nothing to write, so nothing to gate either — return the root already
|
|
146
|
-
// captured rather than round-tripping the document for no reason.
|
|
139
|
+
if (updates.length === 0) {
|
|
147
140
|
return { root: this._sourceRoot };
|
|
148
141
|
}
|
|
149
|
-
|
|
142
|
+
const session = this.requireModelSession();
|
|
143
|
+
for (const update of updates) {
|
|
144
|
+
await this.openForWrite(session, update.uri);
|
|
145
|
+
}
|
|
146
|
+
const documents = await session.updateAll({ updates });
|
|
147
|
+
return { root: primaryChanged ? documents[0].root : this._sourceRoot };
|
|
150
148
|
}
|
|
151
149
|
/**
|
|
152
|
-
* Whether `candidate` differs from the
|
|
150
|
+
* Whether `candidate` differs from the base projection of the same
|
|
153
151
|
* document, and therefore needs writing.
|
|
154
152
|
*
|
|
155
153
|
* **Skipping unchanged documents is correctness, not an optimisation.** A
|
|
156
|
-
* write
|
|
157
|
-
*
|
|
158
|
-
*
|
|
159
|
-
*
|
|
160
|
-
*
|
|
161
|
-
*
|
|
154
|
+
* write re-serializes from the AST, so writing a document that did not
|
|
155
|
+
* change still rewrites its text in the serializer's own layout. Persisting
|
|
156
|
+
* the whole write set unconditionally therefore means a pure layout drag
|
|
157
|
+
* reflows the semantic file, a change the user never asked for and would
|
|
158
|
+
* struggle to attribute. Comments survive that rewrite, but the
|
|
159
|
+
* hand-formatting around them does not.
|
|
162
160
|
*
|
|
163
161
|
* Compared by serialised form. Both sides come from the same encoder walking
|
|
164
162
|
* the same shape, so key order is stable and a string compare is sound here;
|
|
165
163
|
* it is also cheap enough to run per document per write.
|
|
166
164
|
*/
|
|
167
|
-
hasChanged(
|
|
168
|
-
return
|
|
169
|
-
}
|
|
170
|
-
/** Write the primary document, opting into the conflict gate unless `basedOn` is `'anything'`. */
|
|
171
|
-
async persistPrimary(model, basedOn) {
|
|
172
|
-
const document = await this.sharedServices.model.ModelService.update({
|
|
173
|
-
uri: this._sourceUri,
|
|
174
|
-
model,
|
|
175
|
-
clientId: this.clientId,
|
|
176
|
-
basedOn
|
|
177
|
-
});
|
|
178
|
-
return document;
|
|
165
|
+
hasChanged(base, candidate) {
|
|
166
|
+
return base === undefined || JSON.stringify(base) !== JSON.stringify(candidate);
|
|
179
167
|
}
|
|
180
168
|
/**
|
|
181
|
-
*
|
|
182
|
-
*
|
|
183
|
-
*
|
|
184
|
-
*
|
|
169
|
+
* Make sure the diagram's session has `uri` open before the write set is
|
|
170
|
+
* written. Default: open it, a no-op for a document the session already
|
|
171
|
+
* has open. Override to create a document the write set names before it
|
|
172
|
+
* exists, through `session.create`: `updateAll` opens nothing.
|
|
185
173
|
*/
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
uri,
|
|
189
|
-
model,
|
|
190
|
-
clientId: this.clientId,
|
|
191
|
-
basedOn: this.secondaryBasedOn(uri)
|
|
192
|
-
});
|
|
174
|
+
openForWrite(session, uri) {
|
|
175
|
+
return session.open(uri);
|
|
193
176
|
}
|
|
194
177
|
/**
|
|
195
|
-
* What a secondary write declares it was based on. Default
|
|
196
|
-
*
|
|
197
|
-
*
|
|
198
|
-
*
|
|
199
|
-
*
|
|
200
|
-
*
|
|
201
|
-
* ({@link AbstractHydraniumGlspState.snapshotVersionOf}), and returning that
|
|
202
|
-
* value here is the whole opt-in; without it the only place to put the
|
|
203
|
-
* comparison is a copy of {@link persistSecondary}, which then has to be kept
|
|
204
|
-
* in step with the framework's write call.
|
|
205
|
-
*
|
|
206
|
-
* **Opting in buys a conflict report and costs atomicity.** A gated secondary
|
|
207
|
-
* throws mid-set, after earlier secondaries have already been written, and if
|
|
208
|
-
* the reconcile then drops the edit those writes stay. Weigh that against the
|
|
209
|
-
* default, which lets a foreign edit to a secondary be overwritten silently.
|
|
178
|
+
* What a secondary write declares it was based on. Default: the version the
|
|
179
|
+
* secondary had when the source root was last read
|
|
180
|
+
* ({@link AbstractHydraniumGlspState.snapshotVersionOf}), so a foreign edit
|
|
181
|
+
* to it since is reported as a conflict and reconciled rather than
|
|
182
|
+
* overwritten; `'anything'` for a secondary with no recorded version.
|
|
183
|
+
* Return `'anything'` to force secondary writes.
|
|
210
184
|
*/
|
|
211
|
-
secondaryBasedOn(
|
|
212
|
-
return 'anything';
|
|
185
|
+
secondaryBasedOn(uri) {
|
|
186
|
+
return this.snapshotVersionOf(uri) ?? 'anything';
|
|
213
187
|
}
|
|
214
188
|
/**
|
|
215
|
-
* Refetch hook — the current
|
|
216
|
-
*
|
|
189
|
+
* Refetch hook — the current projection across the write set, each document
|
|
190
|
+
* read through {@link AbstractHydraniumGlspState.readCurrentRoot}: theirs,
|
|
191
|
+
* which the conflict resolver replays the user's intent onto.
|
|
217
192
|
* Returns `undefined` when the PRIMARY cannot be read, since a reconcile
|
|
218
193
|
* without it has nothing to merge into; an unreadable secondary is omitted the
|
|
219
194
|
* same way {@link sourceModel} omits one.
|
|
220
195
|
*/
|
|
221
196
|
async refetch() {
|
|
222
|
-
const
|
|
223
|
-
if (!
|
|
197
|
+
const theirs = await this.readCurrentRoot(this._sourceUri);
|
|
198
|
+
if (!theirs) {
|
|
224
199
|
return undefined;
|
|
225
200
|
}
|
|
226
201
|
const secondaries = {};
|
|
227
202
|
for (const uri of this.secondaryUris) {
|
|
228
|
-
const
|
|
229
|
-
if (
|
|
230
|
-
secondaries[uri] = this.projectRoot(
|
|
203
|
+
const root = await this.readCurrentRoot(uri);
|
|
204
|
+
if (root) {
|
|
205
|
+
secondaries[uri] = this.projectRoot(root);
|
|
231
206
|
}
|
|
232
207
|
}
|
|
233
|
-
return { primary: this.projectRoot(
|
|
208
|
+
return { primary: this.projectRoot(theirs), secondaries };
|
|
234
209
|
}
|
|
235
210
|
/** Project a currently-loaded document's root, or `undefined` when it is not loaded. */
|
|
236
211
|
projectDocument(uri) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reconciling-multi-document-glsp-state.js","sourceRoot":"","sources":["../../src/state/reconciling-multi-document-glsp-state.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;;;;;;;AAGlF,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"reconciling-multi-document-glsp-state.js","sourceRoot":"","sources":["../../src/state/reconciling-multi-document-glsp-state.ts"],"names":[],"mappings":"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"}
|
|
@@ -23,16 +23,16 @@ import { AbstractHydraniumGlspState } from './abstract-hydranium-glsp-state.js';
|
|
|
23
23
|
* field-level shape is what lets `fast-json-patch` diff per field, so undo /
|
|
24
24
|
* redo and forward-write reconcile act per field instead of clobbering the
|
|
25
25
|
* whole document.
|
|
26
|
-
* - {@link
|
|
26
|
+
* - {@link base} — the last in-sync projection, captured on every
|
|
27
27
|
* {@link setSourceRoot}. A forward-write conflict reconciles the user's
|
|
28
|
-
* intent (
|
|
28
|
+
* intent (base → ours) against the server's current root (theirs).
|
|
29
29
|
* - {@link updateSourceModel} — the concrete reconcile template: persist,
|
|
30
30
|
* and on a `ConflictError` consult the injected `conflictResolver` and act
|
|
31
31
|
* on the merged / no-op / conflict / unavailable outcome.
|
|
32
32
|
* - {@link persist} / {@link refetch} — the only I/O seams. Defaults route
|
|
33
|
-
* through `
|
|
34
|
-
*
|
|
35
|
-
*
|
|
33
|
+
* through the diagram session's `update` and `ModelService.validated`;
|
|
34
|
+
* adopters whose document round-trip differs override these without
|
|
35
|
+
* touching the orchestration.
|
|
36
36
|
*
|
|
37
37
|
* Adopters whose source model is whole-document text (a bare `{ text }`
|
|
38
38
|
* source model) or that are read-only do NOT extend this class — they extend
|
|
@@ -44,12 +44,12 @@ import { AbstractHydraniumGlspState } from './abstract-hydranium-glsp-state.js';
|
|
|
44
44
|
export declare class ReconcilingTransferHydraniumGlspState<TRoot extends AstNode, TSourceModel extends TransferElement> extends AbstractHydraniumGlspState<TRoot, TSourceModel> implements JsonModelState<TSourceModel> {
|
|
45
45
|
/**
|
|
46
46
|
* Last in-sync source-model projection, captured on every
|
|
47
|
-
* {@link setSourceRoot} (initial load + post-update). The
|
|
47
|
+
* {@link setSourceRoot} (initial load + post-update). The base a
|
|
48
48
|
* forward-write conflict reconciles against: it stays the pre-command
|
|
49
49
|
* state because operation handlers mutate `_sourceRoot` in place during
|
|
50
50
|
* `execute` while `setSourceRoot` only re-runs once the write commits.
|
|
51
51
|
*/
|
|
52
|
-
protected
|
|
52
|
+
protected base?: TSourceModel;
|
|
53
53
|
/**
|
|
54
54
|
* Persisted-shape projection of the current source root, consumed by GLSP's
|
|
55
55
|
* {@link JsonModelState} read side and recorded for field-level undo / redo.
|
|
@@ -63,7 +63,7 @@ export declare class ReconcilingTransferHydraniumGlspState<TRoot extends AstNode
|
|
|
63
63
|
/**
|
|
64
64
|
* Persist `model` back to the document store, then capture the resulting
|
|
65
65
|
* AST root. On a `ConflictError` (the based-on version was superseded),
|
|
66
|
-
* reconcile the user's intent against the
|
|
66
|
+
* reconcile the user's intent against the server's current root via the bound
|
|
67
67
|
* `conflictResolver` and act on the outcome — one declarative policy
|
|
68
68
|
* (force = last-writer-wins, reconciling = field-level merge) shared with
|
|
69
69
|
* undo / redo.
|
|
@@ -71,8 +71,9 @@ export declare class ReconcilingTransferHydraniumGlspState<TRoot extends AstNode
|
|
|
71
71
|
updateSourceModel(model: TSourceModel, basedOn?: BasedOn): Promise<void>;
|
|
72
72
|
/**
|
|
73
73
|
* Persist hook — the only write-side I/O. Default routes the structured
|
|
74
|
-
* model through `
|
|
75
|
-
* the `ConflictError` gate
|
|
74
|
+
* model through the diagram session's `update` (serialize → reparse),
|
|
75
|
+
* opting into the `ConflictError` gate unless `basedOn` is `'anything'`,
|
|
76
|
+
* and throws without a session. Adopters whose document
|
|
76
77
|
* round-trip differs override this; the orchestration in
|
|
77
78
|
* {@link updateSourceModel} is unchanged.
|
|
78
79
|
*/
|
|
@@ -80,11 +81,11 @@ export declare class ReconcilingTransferHydraniumGlspState<TRoot extends AstNode
|
|
|
80
81
|
root: TRoot;
|
|
81
82
|
}>;
|
|
82
83
|
/**
|
|
83
|
-
* Refetch hook —
|
|
84
|
-
* projection (or `undefined` when unavailable)
|
|
85
|
-
* replays the user's intent
|
|
86
|
-
*
|
|
87
|
-
* adopters override alongside {@link persist}.
|
|
84
|
+
* Refetch hook — the stored text parsed afresh, as a persisted-shape
|
|
85
|
+
* projection (or `undefined` when unavailable): theirs, which the
|
|
86
|
+
* `conflictResolver` replays the user's intent onto. Default uses
|
|
87
|
+
* {@link AbstractHydraniumGlspState.readCurrentRoot} + the framework
|
|
88
|
+
* encoder's `'grammar'` mode; adopters override alongside {@link persist}.
|
|
88
89
|
*/
|
|
89
90
|
protected refetch(): Promise<TSourceModel | undefined>;
|
|
90
91
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reconciling-transfer-hydranium-glsp-state.d.ts","sourceRoot":"","sources":["../../src/state/reconciling-transfer-hydranium-glsp-state.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAElF,OAAO,EAAE,KAAK,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAE3D,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,KAAK,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACzE,OAAO,EAAE,0BAA0B,EAAE,MAAM,oCAAoC,CAAC;AAGhF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,qBACa,qCAAqC,CAAC,KAAK,SAAS,OAAO,EAAE,YAAY,SAAS,eAAe,CAC3G,SAAQ,0BAA0B,CAAC,KAAK,EAAE,YAAY,CACtD,YAAW,cAAc,CAAC,YAAY,CAAC;IAEvC;;;;;;OAMG;IACH,SAAS,CAAC,
|
|
1
|
+
{"version":3,"file":"reconciling-transfer-hydranium-glsp-state.d.ts","sourceRoot":"","sources":["../../src/state/reconciling-transfer-hydranium-glsp-state.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAElF,OAAO,EAAE,KAAK,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAE3D,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,KAAK,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACzE,OAAO,EAAE,0BAA0B,EAAE,MAAM,oCAAoC,CAAC;AAGhF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,qBACa,qCAAqC,CAAC,KAAK,SAAS,OAAO,EAAE,YAAY,SAAS,eAAe,CAC3G,SAAQ,0BAA0B,CAAC,KAAK,EAAE,YAAY,CACtD,YAAW,cAAc,CAAC,YAAY,CAAC;IAEvC;;;;;;OAMG;IACH,SAAS,CAAC,IAAI,CAAC,EAAE,YAAY,CAAC;IAE9B;;;;;;;OAOG;IACH,IAAI,WAAW,IAAI,YAAY,CAE9B;IAEQ,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,GAAG,IAAI;IAKtD;;;;;;;OAOG;IACG,iBAAiB,CAAC,KAAK,EAAE,YAAY,EAAE,OAAO,GAAE,OAAsB,GAAG,OAAO,CAAC,IAAI,CAAC;IAiB5F;;;;;;;OAOG;cACa,OAAO,CAAC,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC;QAAE,IAAI,EAAE,KAAK,CAAA;KAAE,CAAC;IAKxF;;;;;;OAMG;cACa,OAAO,IAAI,OAAO,CAAC,YAAY,GAAG,SAAS,CAAC;CAI9D"}
|