@lionweb/class-core 0.7.0-beta.9 → 0.7.0
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/CHANGELOG.md +18 -1
- package/README.md +6 -6
- package/dist/LionCore_builtins.g.d.ts +2 -2
- package/dist/LionCore_builtins.g.d.ts.map +1 -1
- package/dist/LionCore_builtins.g.js +1 -1
- package/dist/LionCore_builtins.g.js.map +1 -1
- package/dist/base-types.d.ts +7 -11
- package/dist/base-types.d.ts.map +1 -1
- package/dist/base-types.js +3 -28
- package/dist/base-types.js.map +1 -1
- package/dist/convenience.d.ts +10 -9
- package/dist/convenience.d.ts.map +1 -1
- package/dist/convenience.js +12 -11
- package/dist/convenience.js.map +1 -1
- package/dist/deltas/appliers.d.ts +5 -4
- package/dist/deltas/appliers.d.ts.map +1 -1
- package/dist/deltas/appliers.js +369 -163
- package/dist/deltas/appliers.js.map +1 -1
- package/dist/deltas/compositor.d.ts +51 -0
- package/dist/deltas/compositor.d.ts.map +1 -0
- package/dist/deltas/compositor.js +95 -0
- package/dist/deltas/compositor.js.map +1 -0
- package/dist/deltas/index.d.ts +2 -1
- package/dist/deltas/index.d.ts.map +1 -1
- package/dist/deltas/index.js +2 -1
- package/dist/deltas/index.js.map +1 -1
- package/dist/deltas/inverters.d.ts.map +1 -1
- package/dist/deltas/inverters.js +91 -28
- package/dist/deltas/inverters.js.map +1 -1
- package/dist/deltas/receivers.d.ts +39 -0
- package/dist/deltas/receivers.d.ts.map +1 -0
- package/dist/deltas/receivers.js +60 -0
- package/dist/deltas/receivers.js.map +1 -0
- package/dist/deltas/serialization/deserializer.g.d.ts.map +1 -1
- package/dist/deltas/serialization/deserializer.g.js +167 -59
- package/dist/deltas/serialization/deserializer.g.js.map +1 -1
- package/dist/deltas/serialization/serializer-helpers.d.ts +1 -1
- package/dist/deltas/serialization/serializer-helpers.d.ts.map +1 -1
- package/dist/deltas/serialization/serializer-helpers.js +3 -4
- package/dist/deltas/serialization/serializer-helpers.js.map +1 -1
- package/dist/deltas/serialization/serializer.g.d.ts +2 -2
- package/dist/deltas/serialization/serializer.g.d.ts.map +1 -1
- package/dist/deltas/serialization/serializer.g.js +186 -47
- package/dist/deltas/serialization/serializer.g.js.map +1 -1
- package/dist/deltas/serialization/types.g.d.ts +156 -43
- package/dist/deltas/serialization/types.g.d.ts.map +1 -1
- package/dist/deltas/types.g.d.ts +155 -55
- package/dist/deltas/types.g.d.ts.map +1 -1
- package/dist/deltas/types.g.js +170 -57
- package/dist/deltas/types.g.js.map +1 -1
- package/dist/deserializer.d.ts +6 -6
- package/dist/deserializer.d.ts.map +1 -1
- package/dist/deserializer.js +16 -27
- package/dist/deserializer.js.map +1 -1
- package/dist/duplicator.d.ts.map +1 -1
- package/dist/duplicator.js.map +1 -1
- package/dist/factory.d.ts +10 -2
- package/dist/factory.d.ts.map +1 -1
- package/dist/factory.js +25 -16
- package/dist/factory.js.map +1 -1
- package/dist/id-mapping.d.ts +31 -3
- package/dist/id-mapping.d.ts.map +1 -1
- package/dist/id-mapping.js +46 -14
- package/dist/id-mapping.js.map +1 -1
- package/dist/serializer.d.ts.map +1 -1
- package/dist/textualizer.d.ts +1 -1
- package/dist/textualizer.d.ts.map +1 -1
- package/dist/textualizer.js +1 -1
- package/dist/textualizer.js.map +1 -1
- package/dist/value-managers/annotations.d.ts +5 -0
- package/dist/value-managers/annotations.d.ts.map +1 -1
- package/dist/value-managers/annotations.js +31 -3
- package/dist/value-managers/annotations.js.map +1 -1
- package/dist/value-managers/base.d.ts +2 -2
- package/dist/value-managers/base.d.ts.map +1 -1
- package/dist/value-managers/base.js +4 -4
- package/dist/value-managers/base.js.map +1 -1
- package/dist/value-managers/containments.d.ts +4 -1
- package/dist/value-managers/containments.d.ts.map +1 -1
- package/dist/value-managers/containments.js +151 -20
- package/dist/value-managers/containments.js.map +1 -1
- package/dist/value-managers/properties.d.ts.map +1 -1
- package/dist/value-managers/properties.js +1 -0
- package/dist/value-managers/properties.js.map +1 -1
- package/dist/value-managers/references.d.ts +3 -0
- package/dist/value-managers/references.d.ts.map +1 -1
- package/dist/value-managers/references.js +26 -8
- package/dist/value-managers/references.js.map +1 -1
- package/package.json +34 -37
- package/src/LionCore_builtins.g.ts +2 -2
- package/src/base-types.ts +6 -32
- package/src/convenience.ts +15 -14
- package/src/deltas/appliers.ts +377 -177
- package/src/deltas/compositor.ts +107 -0
- package/src/deltas/index.ts +3 -1
- package/src/deltas/inverters.ts +108 -36
- package/src/deltas/receivers.ts +92 -0
- package/src/deltas/serialization/deserializer.g.ts +185 -64
- package/src/deltas/serialization/serializer-helpers.ts +3 -10
- package/src/deltas/serialization/serializer.g.ts +242 -63
- package/src/deltas/serialization/types.g.ts +190 -51
- package/src/deltas/types.g.ts +190 -51
- package/src/deserializer.ts +32 -43
- package/src/duplicator.ts +1 -1
- package/src/factory.ts +31 -17
- package/src/id-mapping.ts +43 -5
- package/src/textualizer.ts +1 -1
- package/src/value-managers/annotations.ts +28 -2
- package/src/value-managers/base.ts +4 -4
- package/src/value-managers/containments.ts +144 -20
- package/src/value-managers/properties.ts +1 -0
- package/src/value-managers/references.ts +28 -8
- package/dist/deltas/handlers.d.ts +0 -17
- package/dist/deltas/handlers.d.ts.map +0 -1
- package/dist/deltas/handlers.js +0 -43
- package/dist/deltas/handlers.js.map +0 -1
- package/src/deltas/handlers.ts +0 -64
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
// Copyright 2025 TRUMPF Laser SE and other contributors
|
|
2
|
+
//
|
|
3
|
+
// Licensed under the Apache License, Version 2.0 (the "License")
|
|
4
|
+
// you may not use this file except in compliance with the License.
|
|
5
|
+
// You may obtain a copy of the License at
|
|
6
|
+
//
|
|
7
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
//
|
|
9
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
// See the License for the specific language governing permissions and
|
|
13
|
+
// limitations under the License.
|
|
14
|
+
//
|
|
15
|
+
// SPDX-FileCopyrightText: 2025 TRUMPF Laser SE and other contributors
|
|
16
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
17
|
+
|
|
18
|
+
import { CompositeDelta, DeltaReceiver, IDelta } from "../index.js"
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* A *delta compositor* is used to *aggregate* deltas as {@link CompositeDelta composite deltas}.
|
|
23
|
+
*
|
|
24
|
+
* Usage:
|
|
25
|
+
* ```typescript
|
|
26
|
+
* const compositor = new Compositor(downstreamReceiveDelta);
|
|
27
|
+
* compositor.openComposite();
|
|
28
|
+
* // ...
|
|
29
|
+
* compositor.upstreamReceiveDelta(<delta>);
|
|
30
|
+
* // ...
|
|
31
|
+
* compositor.closeComposite();
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
export class DeltaCompositor {
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* The {@link DeltaReceiver} implementation that either forwards to the given downstream delta handle
|
|
38
|
+
* or gathers deltas into composite deltas to forward to the downstream delta receiver later.
|
|
39
|
+
*/
|
|
40
|
+
readonly upstreamReceiveDelta: DeltaReceiver;
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* An array of arrays of {@link IDelta deltas}, comprising a “stack”.
|
|
44
|
+
*
|
|
45
|
+
* Invariants:
|
|
46
|
+
* - (I1) composite has been opened ⇔ `this.deltasInComposite !== undefined` / `Array.isArray(this.deltasInComposite)`
|
|
47
|
+
* - (I2) this.deltasStack is either undefined or an array containing at least one array
|
|
48
|
+
*/
|
|
49
|
+
private deltasStack: IDelta[][] | undefined = undefined;
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* @param downstreamReceiveDelta the {@link DeltaReceiver} that deltas get passed to.
|
|
53
|
+
* @param maximumNestingDepth the maximum depth that composites can be nested.
|
|
54
|
+
* A maximum depth of e.g. 1 means that at most 1 composite can be open at any time.
|
|
55
|
+
*/
|
|
56
|
+
constructor(private readonly downstreamReceiveDelta: DeltaReceiver, private readonly maximumNestingDepth: number = Infinity) {
|
|
57
|
+
if (maximumNestingDepth !== Infinity && (!Number.isInteger(maximumNestingDepth) || maximumNestingDepth < 0)) {
|
|
58
|
+
throw new Error(`maximum nesting depth must be a non-negative integer`);
|
|
59
|
+
}
|
|
60
|
+
this.upstreamReceiveDelta = (delta) => {
|
|
61
|
+
if (this.deltasStack === undefined) {
|
|
62
|
+
// pass on immediately:
|
|
63
|
+
this.downstreamReceiveDelta(delta);
|
|
64
|
+
} else {
|
|
65
|
+
// store for later:
|
|
66
|
+
this.deltasStack[this.deltasStack.length - 1].push(delta); // (I2)
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Opens a composite, meaning that all deltas passed to the {@link upstreamReceiveDelta} are gathered into a composite delta
|
|
73
|
+
* that gets forwarded to the downstream delta receiver as soon as the composite is closed.
|
|
74
|
+
*
|
|
75
|
+
* Composites can be nested, to the maximum depth configured through this class’ constructor,
|
|
76
|
+
* beyond which an error gets thrown.
|
|
77
|
+
*/
|
|
78
|
+
openComposite = (): void => {
|
|
79
|
+
if (this.deltasStack === undefined) {
|
|
80
|
+
this.deltasStack = []; // ==> (I1) + 1st half of (I2)
|
|
81
|
+
}
|
|
82
|
+
if (this.deltasStack.length >= this.maximumNestingDepth) {
|
|
83
|
+
throw new Error(`attempt occurred to start a nested composition exceeding the maximum nesting depth`)
|
|
84
|
+
}
|
|
85
|
+
this.deltasStack.push([]); // ==> 2nd half of (I2)
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Closes the current composite, producing the deltas gathered for this composite into a composite delta.
|
|
90
|
+
* Composites can be nested, and deltas only get forwarded to the downstream delta receiver after the top-level composite has been closed.
|
|
91
|
+
*/
|
|
92
|
+
closeComposite = (): void => {
|
|
93
|
+
if (this.deltasStack === undefined) {
|
|
94
|
+
throw new Error(`attempt occurred to finish a composite without one being started`);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const parts = this.deltasStack.pop()!; // is an array because of (I2)
|
|
98
|
+
if (this.deltasStack.length === 0) { // last array popped from stack
|
|
99
|
+
this.deltasStack = undefined; // maintain (I2)
|
|
100
|
+
}
|
|
101
|
+
if (parts.length > 0) {
|
|
102
|
+
this.upstreamReceiveDelta(new CompositeDelta(parts));
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
}
|
|
107
|
+
|
package/src/deltas/index.ts
CHANGED
|
@@ -17,7 +17,9 @@
|
|
|
17
17
|
|
|
18
18
|
export * from "./appliers.js";
|
|
19
19
|
export * from "./base.js";
|
|
20
|
-
export * from "./
|
|
20
|
+
export * from "./compositor.js";
|
|
21
21
|
export * from "./inverters.js";
|
|
22
|
+
export * from "./receivers.js";
|
|
22
23
|
export * from "./types.g.js";
|
|
23
24
|
export * from "./serialization/index.js";
|
|
25
|
+
|
package/src/deltas/inverters.ts
CHANGED
|
@@ -18,23 +18,36 @@
|
|
|
18
18
|
import {
|
|
19
19
|
AnnotationAddedDelta,
|
|
20
20
|
AnnotationDeletedDelta,
|
|
21
|
+
AnnotationMovedAndReplacedFromOtherParentDelta,
|
|
22
|
+
AnnotationMovedAndReplacedInSameParentDelta,
|
|
21
23
|
AnnotationMovedFromOtherParentDelta,
|
|
22
24
|
AnnotationMovedInSameParentDelta,
|
|
23
25
|
AnnotationReplacedDelta,
|
|
24
26
|
ChildAddedDelta,
|
|
25
27
|
ChildDeletedDelta,
|
|
26
|
-
|
|
28
|
+
ChildMovedAndReplacedFromOtherContainmentDelta,
|
|
29
|
+
ChildMovedAndReplacedFromOtherContainmentInSameParentDelta,
|
|
30
|
+
ChildMovedAndReplacedInSameContainmentDelta,
|
|
31
|
+
ChildMovedFromOtherContainmentDelta,
|
|
32
|
+
ChildMovedFromOtherContainmentInSameParentDelta,
|
|
27
33
|
ChildMovedInSameContainmentDelta,
|
|
28
34
|
ChildReplacedDelta,
|
|
35
|
+
CompositeDelta,
|
|
36
|
+
EntryMovedAndReplacedFromOtherReferenceDelta,
|
|
37
|
+
EntryMovedAndReplacedFromOtherReferenceInSameParentDelta,
|
|
38
|
+
EntryMovedAndReplacedInSameReferenceDelta,
|
|
39
|
+
EntryMovedFromOtherReferenceDelta,
|
|
40
|
+
EntryMovedFromOtherReferenceInSameParentDelta,
|
|
41
|
+
EntryMovedInSameReferenceDelta,
|
|
29
42
|
NoOpDelta,
|
|
43
|
+
PartitionAddedDelta,
|
|
44
|
+
PartitionDeletedDelta,
|
|
30
45
|
PropertyAddedDelta,
|
|
31
46
|
PropertyChangedDelta,
|
|
32
47
|
PropertyDeletedDelta,
|
|
33
48
|
ReferenceAddedDelta,
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
ReferenceMovedInSameReferenceDelta,
|
|
37
|
-
ReferenceReplacedDelta
|
|
49
|
+
ReferenceChangedDelta,
|
|
50
|
+
ReferenceDeletedDelta
|
|
38
51
|
} from "./types.g.js"
|
|
39
52
|
import { IDelta } from "./base.js"
|
|
40
53
|
|
|
@@ -44,52 +57,57 @@ import { IDelta } from "./base.js"
|
|
|
44
57
|
* in the sense that it undoes that delta after it has been applied.
|
|
45
58
|
*/
|
|
46
59
|
export const invertDelta = (delta: IDelta): IDelta => {
|
|
47
|
-
if (delta instanceof
|
|
48
|
-
return delta;
|
|
60
|
+
if (delta instanceof PartitionAddedDelta) {
|
|
61
|
+
return new PartitionDeletedDelta(delta.newPartition);
|
|
49
62
|
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
return new PropertyDeletedDelta(delta.container, delta.property, delta.value);
|
|
63
|
+
if (delta instanceof PartitionDeletedDelta) {
|
|
64
|
+
return new PartitionAddedDelta(delta.deletedPartition);
|
|
53
65
|
}
|
|
54
|
-
if (delta instanceof
|
|
55
|
-
return new
|
|
66
|
+
if (delta instanceof PropertyAddedDelta) {
|
|
67
|
+
return new PropertyDeletedDelta(delta.node, delta.property, delta.value);
|
|
56
68
|
}
|
|
57
69
|
if (delta instanceof PropertyDeletedDelta) {
|
|
58
|
-
return new PropertyAddedDelta(delta.
|
|
70
|
+
return new PropertyAddedDelta(delta.node, delta.property, delta.oldValue);
|
|
71
|
+
}
|
|
72
|
+
if (delta instanceof PropertyChangedDelta) {
|
|
73
|
+
return new PropertyChangedDelta(delta.node, delta.property, delta.newValue, delta.oldValue);
|
|
59
74
|
}
|
|
60
|
-
|
|
61
75
|
if (delta instanceof ChildAddedDelta) {
|
|
62
76
|
return new ChildDeletedDelta(delta.parent, delta.containment, delta.index, delta.newChild);
|
|
63
77
|
}
|
|
64
|
-
if (delta instanceof ChildReplacedDelta) {
|
|
65
|
-
return new ChildReplacedDelta(delta.parent, delta.containment, delta.index, delta.newChild, delta.replacedChild);
|
|
66
|
-
}
|
|
67
|
-
if (delta instanceof ChildMovedDelta) {
|
|
68
|
-
return new ChildMovedDelta(delta.newParent, delta.newContainment, delta.newIndex, delta.oldParent, delta.oldContainment, delta.oldIndex, delta.child);
|
|
69
|
-
}
|
|
70
|
-
if (delta instanceof ChildMovedInSameContainmentDelta) {
|
|
71
|
-
return new ChildMovedInSameContainmentDelta(delta.parent, delta.containment, delta.newIndex, delta.oldIndex, delta.child);
|
|
72
|
-
}
|
|
73
78
|
if (delta instanceof ChildDeletedDelta) {
|
|
74
79
|
return new ChildAddedDelta(delta.parent, delta.containment, delta.index, delta.deletedChild);
|
|
75
80
|
}
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
return new ReferenceDeletedDelta(delta.container, delta.reference, delta.index, delta.newTarget);
|
|
79
|
-
}
|
|
80
|
-
if (delta instanceof ReferenceReplacedDelta) {
|
|
81
|
-
return new ReferenceReplacedDelta(delta.container, delta.reference, delta.index, delta.newTarget, delta.replacedTarget);
|
|
81
|
+
if (delta instanceof ChildReplacedDelta) {
|
|
82
|
+
return new ChildReplacedDelta(delta.parent, delta.containment, delta.index, delta.newChild, delta.replacedChild);
|
|
82
83
|
}
|
|
83
|
-
if (delta instanceof
|
|
84
|
-
return new
|
|
84
|
+
if (delta instanceof ChildMovedFromOtherContainmentDelta) {
|
|
85
|
+
return new ChildMovedFromOtherContainmentDelta(delta.newParent, delta.newContainment, delta.newIndex, delta.oldParent, delta.oldContainment, delta.oldIndex, delta.movedChild);
|
|
85
86
|
}
|
|
86
|
-
if (delta instanceof
|
|
87
|
-
return new
|
|
87
|
+
if (delta instanceof ChildMovedFromOtherContainmentInSameParentDelta) {
|
|
88
|
+
return new ChildMovedFromOtherContainmentInSameParentDelta(delta.parent, delta.newContainment, delta.newIndex, delta.movedChild, delta.oldContainment, delta.oldIndex);
|
|
88
89
|
}
|
|
89
|
-
if (delta instanceof
|
|
90
|
-
return new
|
|
90
|
+
if (delta instanceof ChildMovedInSameContainmentDelta) {
|
|
91
|
+
return new ChildMovedInSameContainmentDelta(delta.parent, delta.containment, delta.newIndex, delta.oldIndex, delta.movedChild);
|
|
92
|
+
}
|
|
93
|
+
if (delta instanceof ChildMovedAndReplacedFromOtherContainmentDelta) {
|
|
94
|
+
return new CompositeDelta([
|
|
95
|
+
new ChildMovedFromOtherContainmentDelta(delta.newParent, delta.newContainment, delta.newIndex, delta.oldParent, delta.oldContainment, delta.oldIndex, delta.movedChild),
|
|
96
|
+
new ChildAddedDelta(delta.newParent, delta.newContainment, delta.newIndex, delta.replacedChild)
|
|
97
|
+
]);
|
|
98
|
+
}
|
|
99
|
+
if (delta instanceof ChildMovedAndReplacedFromOtherContainmentInSameParentDelta) {
|
|
100
|
+
return new CompositeDelta([
|
|
101
|
+
new ChildMovedFromOtherContainmentInSameParentDelta(delta.parent, delta.newContainment, delta.newIndex, delta.movedChild, delta.oldContainment, delta.oldIndex),
|
|
102
|
+
new ChildAddedDelta(delta.parent, delta.newContainment, delta.newIndex, delta.replacedChild)
|
|
103
|
+
]);
|
|
104
|
+
}
|
|
105
|
+
if (delta instanceof ChildMovedAndReplacedInSameContainmentDelta) {
|
|
106
|
+
return new CompositeDelta([
|
|
107
|
+
new ChildMovedInSameContainmentDelta(delta.parent, delta.containment, delta.newIndex, delta.oldIndex, delta.movedChild),
|
|
108
|
+
new ChildAddedDelta(delta.parent, delta.containment, delta.newIndex, delta.replacedChild)
|
|
109
|
+
]);
|
|
91
110
|
}
|
|
92
|
-
|
|
93
111
|
if (delta instanceof AnnotationAddedDelta) {
|
|
94
112
|
return new AnnotationDeletedDelta(delta.parent, delta.index, delta.newAnnotation);
|
|
95
113
|
}
|
|
@@ -105,6 +123,60 @@ export const invertDelta = (delta: IDelta): IDelta => {
|
|
|
105
123
|
if (delta instanceof AnnotationMovedInSameParentDelta) {
|
|
106
124
|
return new AnnotationMovedInSameParentDelta(delta.parent, delta.newIndex, delta.oldIndex, delta.movedAnnotation);
|
|
107
125
|
}
|
|
126
|
+
if (delta instanceof AnnotationMovedAndReplacedFromOtherParentDelta) {
|
|
127
|
+
return new CompositeDelta([
|
|
128
|
+
new AnnotationMovedFromOtherParentDelta(delta.newParent, delta.newIndex, delta.oldParent, delta.oldIndex, delta.movedAnnotation),
|
|
129
|
+
new AnnotationAddedDelta(delta.newParent, delta.newIndex, delta.replacedAnnotation)
|
|
130
|
+
]);
|
|
131
|
+
}
|
|
132
|
+
if (delta instanceof AnnotationMovedAndReplacedInSameParentDelta) {
|
|
133
|
+
return new CompositeDelta([
|
|
134
|
+
new AnnotationMovedInSameParentDelta(delta.parent, delta.newIndex, delta.oldIndex, delta.movedAnnotation),
|
|
135
|
+
new AnnotationAddedDelta(delta.parent, delta.newIndex, delta.replacedAnnotation)
|
|
136
|
+
]);
|
|
137
|
+
}
|
|
138
|
+
if (delta instanceof ReferenceAddedDelta) {
|
|
139
|
+
return new ReferenceDeletedDelta(delta.parent, delta.reference, delta.index, delta.newTarget);
|
|
140
|
+
}
|
|
141
|
+
if (delta instanceof ReferenceDeletedDelta) {
|
|
142
|
+
return new ReferenceAddedDelta(delta.parent, delta.reference, delta.index, delta.deletedTarget);
|
|
143
|
+
}
|
|
144
|
+
if (delta instanceof ReferenceChangedDelta) {
|
|
145
|
+
return new ReferenceChangedDelta(delta.parent, delta.reference, delta.index, delta.oldTarget, delta.newTarget);
|
|
146
|
+
}
|
|
147
|
+
if (delta instanceof EntryMovedFromOtherReferenceDelta) {
|
|
148
|
+
return new EntryMovedFromOtherReferenceDelta(delta.newParent, delta.newReference, delta.newIndex, delta.oldParent, delta.oldReference, delta.oldIndex, delta.movedTarget);
|
|
149
|
+
}
|
|
150
|
+
if (delta instanceof EntryMovedFromOtherReferenceInSameParentDelta) {
|
|
151
|
+
return new EntryMovedFromOtherReferenceInSameParentDelta(delta.parent, delta.newReference, delta.newIndex, delta.oldReference, delta.oldIndex, delta.movedTarget);
|
|
152
|
+
}
|
|
153
|
+
if (delta instanceof EntryMovedInSameReferenceDelta) {
|
|
154
|
+
return new EntryMovedInSameReferenceDelta(delta.parent, delta.reference, delta.newIndex, delta.oldIndex, delta.movedTarget);
|
|
155
|
+
}
|
|
156
|
+
if (delta instanceof EntryMovedAndReplacedFromOtherReferenceDelta) {
|
|
157
|
+
return new CompositeDelta([
|
|
158
|
+
new EntryMovedFromOtherReferenceDelta(delta.newParent, delta.newReference, delta.newIndex, delta.oldParent, delta.oldReference, delta.oldIndex, delta.movedTarget),
|
|
159
|
+
new ReferenceAddedDelta(delta.newParent, delta.newReference, delta.newIndex, delta.replacedTarget)
|
|
160
|
+
]);
|
|
161
|
+
}
|
|
162
|
+
if (delta instanceof EntryMovedAndReplacedFromOtherReferenceInSameParentDelta) {
|
|
163
|
+
return new CompositeDelta([
|
|
164
|
+
new EntryMovedFromOtherReferenceInSameParentDelta(delta.parent, delta.newReference, delta.newIndex, delta.oldReference, delta.oldIndex, delta.movedTarget),
|
|
165
|
+
new ReferenceAddedDelta(delta.parent, delta.newReference, delta.newIndex, delta.replacedTarget)
|
|
166
|
+
]);
|
|
167
|
+
}
|
|
168
|
+
if (delta instanceof EntryMovedAndReplacedInSameReferenceDelta) {
|
|
169
|
+
return new CompositeDelta([
|
|
170
|
+
new EntryMovedInSameReferenceDelta(delta.parent, delta.reference, delta.newIndex, delta.oldIndex, delta.movedTarget),
|
|
171
|
+
new ReferenceAddedDelta(delta.parent, delta.reference, delta.newIndex, delta.replacedTarget)
|
|
172
|
+
]);
|
|
173
|
+
}
|
|
174
|
+
if (delta instanceof CompositeDelta) {
|
|
175
|
+
return new CompositeDelta(delta.parts.map(invertDelta));
|
|
176
|
+
}
|
|
177
|
+
if (delta instanceof NoOpDelta) {
|
|
178
|
+
return delta;
|
|
179
|
+
}
|
|
108
180
|
|
|
109
181
|
throw new Error(`inversion of delta of class ${delta.constructor.name} not implemented`);
|
|
110
182
|
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
// Copyright 2025 TRUMPF Laser SE and other contributors
|
|
2
|
+
//
|
|
3
|
+
// Licensed under the Apache License, Version 2.0 (the "License")
|
|
4
|
+
// you may not use this file except in compliance with the License.
|
|
5
|
+
// You may obtain a copy of the License at
|
|
6
|
+
//
|
|
7
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
//
|
|
9
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
// See the License for the specific language governing permissions and
|
|
13
|
+
// limitations under the License.
|
|
14
|
+
//
|
|
15
|
+
// SPDX-FileCopyrightText: 2025 TRUMPF Laser SE and other contributors
|
|
16
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
17
|
+
|
|
18
|
+
import { asPrettyJsonString } from "@lionweb/ts-utils"
|
|
19
|
+
import { IDelta } from "./base.js"
|
|
20
|
+
import { serializeDelta } from "./serialization/index.js"
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* A type for functions that receive deltas.
|
|
24
|
+
*/
|
|
25
|
+
export type DeltaReceiver = (delta: IDelta) => void;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Legacy alias for {@link DeltaReceiver}.
|
|
29
|
+
*/
|
|
30
|
+
export type DeltaHandler = (delta: IDelta) => void;
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* @return a tuple consisting of a {@link DeltaReceiver} implementation (as 1st member) that pushes any received delta unto the tuple's 2nd member: an array of {@link IDelta deltas}.
|
|
34
|
+
* @param printSerializations determines whether the deltas are serialized as JSON and printed to the JavaScript console.
|
|
35
|
+
*/
|
|
36
|
+
export const collectingDeltaReceiver = (printSerializations = false): [DeltaReceiver, IDelta[]] => {
|
|
37
|
+
const deltas: IDelta[] = [];
|
|
38
|
+
const receiveDelta: DeltaReceiver = (delta) => {
|
|
39
|
+
deltas.push(delta);
|
|
40
|
+
if (printSerializations) {
|
|
41
|
+
console.log(asPrettyJsonString(serializeDelta(delta)));
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
return [receiveDelta, deltas];
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Legacy alias for {@link collectingDeltaReceiver}.
|
|
49
|
+
*/
|
|
50
|
+
export const collectingDeltaHandler = collectingDeltaReceiver;
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* An interface for {@link DeltaReceiver delta receivers} that can be switched on and off — “latchingDeltaReceiverFrom”.
|
|
54
|
+
*/
|
|
55
|
+
export interface LatchingDeltaReceiver extends DeltaReceiver {
|
|
56
|
+
latch(emitDeltas: boolean): void;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Legacy alias for {@link LatchingDeltaReceiver}.
|
|
61
|
+
*/
|
|
62
|
+
export interface LatchingDeltaHandler extends LatchingDeltaReceiver {};
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* @return a latching version of the given {@link DeltaReceiver delta receiver}.
|
|
66
|
+
*/
|
|
67
|
+
export const latchingDeltaReceiverFrom = (receiveDelta: DeltaReceiver): LatchingDeltaReceiver => {
|
|
68
|
+
let emitDeltas = false;
|
|
69
|
+
return Object.assign(
|
|
70
|
+
(delta: IDelta) => {
|
|
71
|
+
if (emitDeltas) {
|
|
72
|
+
receiveDelta(delta);
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
latch(emitDeltas_: boolean) {
|
|
77
|
+
emitDeltas = emitDeltas_;
|
|
78
|
+
},
|
|
79
|
+
},
|
|
80
|
+
);
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* @return a {@link DeltaReceiver delta receiver} implementation that forwards received deltas to the given {@link DeltaReceiver delta receivers}.
|
|
86
|
+
* This is necessary e.g. for combining using the delta protocol with an undo mechanism.
|
|
87
|
+
*/
|
|
88
|
+
export const deltaReceiverForwardingTo = (...deltaReceivers: DeltaReceiver[]): DeltaReceiver =>
|
|
89
|
+
(delta) => {
|
|
90
|
+
deltaReceivers.forEach((receiveDelta) => receiveDelta(delta));
|
|
91
|
+
};
|
|
92
|
+
|