@lionweb/class-core 0.7.0-beta.13 → 0.7.0-beta.15
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 +9 -1
- package/dist/base-types.d.ts +0 -4
- package/dist/base-types.d.ts.map +1 -1
- package/dist/base-types.js +0 -25
- package/dist/base-types.js.map +1 -1
- package/dist/deltas/appliers.d.ts.map +1 -1
- package/dist/deltas/appliers.js +2 -1
- package/dist/deltas/appliers.js.map +1 -1
- package/dist/deltas/inverters.d.ts.map +1 -1
- package/dist/deltas/inverters.js +33 -9
- package/dist/deltas/inverters.js.map +1 -1
- package/dist/deltas/receivers.d.ts.map +1 -1
- package/dist/deltas/receivers.js +2 -1
- package/dist/deltas/receivers.js.map +1 -1
- package/dist/deltas/serialization/deserializer.g.d.ts.map +1 -1
- package/dist/deltas/serialization/deserializer.g.js +16 -4
- package/dist/deltas/serialization/deserializer.g.js.map +1 -1
- package/dist/deserializer.d.ts.map +1 -1
- package/dist/deserializer.js +3 -14
- package/dist/deserializer.js.map +1 -1
- package/dist/factory.d.ts +8 -0
- 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 +21 -3
- package/dist/id-mapping.d.ts.map +1 -1
- package/dist/id-mapping.js +37 -17
- package/dist/id-mapping.js.map +1 -1
- package/dist/textualizer.js +1 -1
- package/dist/textualizer.js.map +1 -1
- package/dist/value-managers/annotations.d.ts.map +1 -1
- package/dist/value-managers/annotations.js +1 -2
- package/dist/value-managers/annotations.js.map +1 -1
- package/dist/value-managers/containments.d.ts +2 -2
- package/dist/value-managers/containments.d.ts.map +1 -1
- package/dist/value-managers/containments.js +89 -27
- package/dist/value-managers/containments.js.map +1 -1
- package/dist/value-managers/references.js +2 -2
- package/package.json +34 -34
- package/src/base-types.ts +0 -25
- package/src/deltas/appliers.ts +2 -1
- package/src/deltas/inverters.ts +33 -9
- package/src/deltas/receivers.ts +2 -1
- package/src/deltas/serialization/deserializer.g.ts +19 -7
- package/src/deserializer.ts +3 -19
- package/src/factory.ts +30 -16
- package/src/id-mapping.ts +26 -5
- package/src/textualizer.ts +1 -1
- package/src/value-managers/annotations.ts +2 -2
- package/src/value-managers/containments.ts +87 -27
- package/src/value-managers/references.ts +2 -2
package/package.json
CHANGED
|
@@ -1,36 +1,36 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
2
|
+
"name": "@lionweb/class-core",
|
|
3
|
+
"version": "0.7.0-beta.15",
|
|
4
|
+
"description": "Generic, language-aspecific base types for generated TypeScript APIs",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"typings": "dist/index.d.ts",
|
|
8
|
+
"type": "module",
|
|
9
|
+
"license": "Apache-2.0",
|
|
10
|
+
"repository": {
|
|
11
|
+
"type": "git",
|
|
12
|
+
"url": "git+https://github.com/LionWeb-io/lionweb-typescript.git"
|
|
13
|
+
},
|
|
14
|
+
"bugs": {
|
|
15
|
+
"url": "https://github.com/LionWeb-io/lionweb-typescript/issues"
|
|
16
|
+
},
|
|
17
|
+
"scripts": {
|
|
18
|
+
"clean": "npx rimraf dist node_modules -g lionweb-class-core-*.tgz",
|
|
19
|
+
"build": "npx rimraf dist && tsc",
|
|
20
|
+
"lint": "eslint src",
|
|
21
|
+
"prep:pre-release": "npm run clean && npm install && npm run build",
|
|
22
|
+
"prerelease-alpha": "npm run prep:pre-release",
|
|
23
|
+
"release-alpha": "npm publish --tag alpha",
|
|
24
|
+
"prerelease-beta": "npm run prep:pre-release",
|
|
25
|
+
"release-beta": "npm publish --tag beta",
|
|
26
|
+
"prerelease": "npm run prep:pre-release",
|
|
27
|
+
"release": "npm publish"
|
|
28
|
+
},
|
|
29
|
+
"dependencies": {
|
|
30
|
+
"@lionweb/core": "0.7.0-beta.15",
|
|
31
|
+
"@lionweb/json": "0.7.0-beta.15",
|
|
32
|
+
"@lionweb/ts-utils": "0.7.0-beta.15",
|
|
33
|
+
"littoral-templates": "0.5.0",
|
|
34
|
+
"mobx": "6.13.7"
|
|
35
|
+
}
|
|
36
36
|
}
|
package/src/base-types.ts
CHANGED
|
@@ -351,28 +351,3 @@ export interface ILanguageBase {
|
|
|
351
351
|
enumLiteralFrom<T>(enumerationLiteral: EnumerationLiteral): T;
|
|
352
352
|
}
|
|
353
353
|
|
|
354
|
-
|
|
355
|
-
/**
|
|
356
|
-
* Removes the given child node from its parent, and returns its containment index.
|
|
357
|
-
*/
|
|
358
|
-
export const removeFromParent = (parent: INodeBase | undefined, child: INodeBase): number => {
|
|
359
|
-
if (parent === undefined) {
|
|
360
|
-
throw new Error(`can't remove an orphan from its parent`);
|
|
361
|
-
}
|
|
362
|
-
if (child.containment instanceof Containment) {
|
|
363
|
-
const valueManager = parent.getContainmentValueManager(child.containment);
|
|
364
|
-
if (valueManager instanceof SingleContainmentValueManager) {
|
|
365
|
-
valueManager.setDirectly(undefined);
|
|
366
|
-
return 0;
|
|
367
|
-
} else if (valueManager instanceof MultiContainmentValueManager) {
|
|
368
|
-
return valueManager.removeDirectly(child);
|
|
369
|
-
} else {
|
|
370
|
-
throw new Error(`don't know how to remove a child that's contained through a value manager of type ${valueManager.constructor.name}`);
|
|
371
|
-
}
|
|
372
|
-
}
|
|
373
|
-
if (child.containment === null) {
|
|
374
|
-
return parent.annotationsValueManager.removeDirectly(child);
|
|
375
|
-
}
|
|
376
|
-
throw new Error(`not going to remove a child from its parent without knowing how it's contained`);
|
|
377
|
-
}
|
|
378
|
-
|
package/src/deltas/appliers.ts
CHANGED
|
@@ -66,7 +66,8 @@ import { IDelta } from "./base.js"
|
|
|
66
66
|
* If an {@link IdMapping} is provided, the {@link INodeBase nodes} relevant for the delta are looked up from that;
|
|
67
67
|
* otherwise, the delta is applied directly to (object-)referenced nodes.
|
|
68
68
|
*
|
|
69
|
-
* This is an internal function, solely meant to DRY the delta application
|
|
69
|
+
* This is an internal function, solely meant to DRY the delta application
|
|
70
|
+
* with and without lookup in an {@link IdMapping ID mapping object}.
|
|
70
71
|
*/
|
|
71
72
|
const deltaApplier = (idMapping?: IdMapping, updatablePartitions?: () => INodeBase[]) =>
|
|
72
73
|
(delta: IDelta): void => {
|
package/src/deltas/inverters.ts
CHANGED
|
@@ -91,13 +91,22 @@ export const invertDelta = (delta: IDelta): IDelta => {
|
|
|
91
91
|
return new ChildMovedInSameContainmentDelta(delta.parent, delta.containment, delta.newIndex, delta.oldIndex, delta.movedChild);
|
|
92
92
|
}
|
|
93
93
|
if (delta instanceof ChildMovedAndReplacedFromOtherContainmentDelta) {
|
|
94
|
-
|
|
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
|
+
]);
|
|
95
98
|
}
|
|
96
99
|
if (delta instanceof ChildMovedAndReplacedFromOtherContainmentInSameParentDelta) {
|
|
97
|
-
|
|
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
|
+
]);
|
|
98
104
|
}
|
|
99
105
|
if (delta instanceof ChildMovedAndReplacedInSameContainmentDelta) {
|
|
100
|
-
|
|
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
|
+
]);
|
|
101
110
|
}
|
|
102
111
|
if (delta instanceof AnnotationAddedDelta) {
|
|
103
112
|
return new AnnotationDeletedDelta(delta.parent, delta.index, delta.newAnnotation);
|
|
@@ -115,10 +124,16 @@ export const invertDelta = (delta: IDelta): IDelta => {
|
|
|
115
124
|
return new AnnotationMovedInSameParentDelta(delta.parent, delta.newIndex, delta.oldIndex, delta.movedAnnotation);
|
|
116
125
|
}
|
|
117
126
|
if (delta instanceof AnnotationMovedAndReplacedFromOtherParentDelta) {
|
|
118
|
-
|
|
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
|
+
]);
|
|
119
131
|
}
|
|
120
132
|
if (delta instanceof AnnotationMovedAndReplacedInSameParentDelta) {
|
|
121
|
-
|
|
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
|
+
]);
|
|
122
137
|
}
|
|
123
138
|
if (delta instanceof ReferenceAddedDelta) {
|
|
124
139
|
return new ReferenceDeletedDelta(delta.parent, delta.reference, delta.index, delta.newTarget);
|
|
@@ -133,19 +148,28 @@ export const invertDelta = (delta: IDelta): IDelta => {
|
|
|
133
148
|
return new EntryMovedFromOtherReferenceDelta(delta.newParent, delta.newReference, delta.newIndex, delta.oldParent, delta.oldReference, delta.oldIndex, delta.movedTarget);
|
|
134
149
|
}
|
|
135
150
|
if (delta instanceof EntryMovedFromOtherReferenceInSameParentDelta) {
|
|
136
|
-
|
|
151
|
+
return new EntryMovedFromOtherReferenceInSameParentDelta(delta.parent, delta.newReference, delta.newIndex, delta.oldReference, delta.oldIndex, delta.movedTarget);
|
|
137
152
|
}
|
|
138
153
|
if (delta instanceof EntryMovedInSameReferenceDelta) {
|
|
139
154
|
return new EntryMovedInSameReferenceDelta(delta.parent, delta.reference, delta.newIndex, delta.oldIndex, delta.movedTarget);
|
|
140
155
|
}
|
|
141
156
|
if (delta instanceof EntryMovedAndReplacedFromOtherReferenceDelta) {
|
|
142
|
-
|
|
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
|
+
]);
|
|
143
161
|
}
|
|
144
162
|
if (delta instanceof EntryMovedAndReplacedFromOtherReferenceInSameParentDelta) {
|
|
145
|
-
return new
|
|
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
|
+
]);
|
|
146
167
|
}
|
|
147
168
|
if (delta instanceof EntryMovedAndReplacedInSameReferenceDelta) {
|
|
148
|
-
|
|
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
|
+
]);
|
|
149
173
|
}
|
|
150
174
|
if (delta instanceof CompositeDelta) {
|
|
151
175
|
return new CompositeDelta(delta.parts.map(invertDelta));
|
package/src/deltas/receivers.ts
CHANGED
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
// SPDX-FileCopyrightText: 2025 TRUMPF Laser SE and other contributors
|
|
16
16
|
// SPDX-License-Identifier: Apache-2.0
|
|
17
17
|
|
|
18
|
+
import { asPrettyJsonString } from "@lionweb/ts-utils"
|
|
18
19
|
import { IDelta } from "./base.js"
|
|
19
20
|
import { serializeDelta } from "./serialization/index.js"
|
|
20
21
|
|
|
@@ -37,7 +38,7 @@ export const collectingDeltaReceiver = (printSerializations = false): [DeltaRece
|
|
|
37
38
|
const receiveDelta: DeltaReceiver = (delta) => {
|
|
38
39
|
deltas.push(delta);
|
|
39
40
|
if (printSerializations) {
|
|
40
|
-
console.log(
|
|
41
|
+
console.log(asPrettyJsonString(serializeDelta(delta)));
|
|
41
42
|
}
|
|
42
43
|
};
|
|
43
44
|
return [receiveDelta, deltas];
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
// Warning: this file is generated!
|
|
19
19
|
// Modifying it by hand is useless at best, and sabotage at worst.
|
|
20
20
|
|
|
21
|
-
import { Containment, MemoisingSymbolTable, Property, Reference } from "@lionweb/core";
|
|
21
|
+
import { Containment, Feature, MemoisingSymbolTable, Property, Reference } from "@lionweb/core";
|
|
22
22
|
import { LionWebJsonMetaPointer } from "@lionweb/json";
|
|
23
23
|
|
|
24
24
|
import { ILanguageBase, INodeBase } from "../../base-types.js";
|
|
@@ -62,14 +62,26 @@ import {
|
|
|
62
62
|
import { IDelta } from "../base.js";
|
|
63
63
|
|
|
64
64
|
|
|
65
|
+
type FeatureResolver<FT extends Feature> = (metaPointer: LionWebJsonMetaPointer, container: INodeBase) => FT;
|
|
66
|
+
|
|
65
67
|
export const deltaDeserializer = (languageBases: ILanguageBase[], idMapping: IdMapping): DeltaDeserializer => {
|
|
66
68
|
const symbolTable = new MemoisingSymbolTable(languageBases.map(({language}) => language));
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
69
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
70
|
+
const featureResolverFor = <FT extends Feature>(featureClazz: new (...args: any[]) => FT): FeatureResolver<FT> =>
|
|
71
|
+
(metaPointer, container) => {
|
|
72
|
+
const featureLocationMessage = () => `feature with meta-pointer ${JSON.stringify(metaPointer)} on instance with ID="${container.id}" with meta-pointer ${JSON.stringify(container.classifier.metaPointer())}`;
|
|
73
|
+
const feature = symbolTable.featureMatching(container.classifier.metaPointer(), metaPointer);
|
|
74
|
+
if (feature === undefined) {
|
|
75
|
+
throw new Error(`couldn't resolve ${featureLocationMessage()}`); // fail early <== unrecoverable
|
|
76
|
+
}
|
|
77
|
+
if (!(feature instanceof featureClazz)) {
|
|
78
|
+
throw new Error(`${featureLocationMessage()} is not a ${featureClazz.name} but a ${feature.constructor.name}`); // fail early <== unrecoverable
|
|
79
|
+
}
|
|
80
|
+
return feature as FT;
|
|
81
|
+
}
|
|
82
|
+
const resolvedPropertyFrom = featureResolverFor(Property);
|
|
83
|
+
const resolvedContainmentFrom = featureResolverFor(Containment);
|
|
84
|
+
const resolvedReferenceFrom = featureResolverFor(Reference);
|
|
73
85
|
const deserializedDelta = (delta: SerializedDelta): IDelta => {
|
|
74
86
|
switch (delta.kind) {
|
|
75
87
|
case "PartitionAdded": {
|
package/src/deserializer.ts
CHANGED
|
@@ -21,7 +21,6 @@ import {
|
|
|
21
21
|
Containment,
|
|
22
22
|
defaultSimplisticHandler,
|
|
23
23
|
Enumeration,
|
|
24
|
-
Language,
|
|
25
24
|
MemoisingSymbolTable,
|
|
26
25
|
PrimitiveType,
|
|
27
26
|
Property,
|
|
@@ -34,6 +33,7 @@ import { LionWebId, LionWebJsonChunk, LionWebJsonNode } from "@lionweb/json"
|
|
|
34
33
|
import { byIdMap, keepDefineds } from "@lionweb/ts-utils"
|
|
35
34
|
|
|
36
35
|
import { DeltaReceiver, IdMapping, ILanguageBase, INodeBase } from "./index.js"
|
|
36
|
+
import { combinedLanguageBaseLookupFor } from "./factory.js"
|
|
37
37
|
import { NodesToInstall } from "./linking.js"
|
|
38
38
|
|
|
39
39
|
|
|
@@ -48,21 +48,6 @@ export type Deserializer<T> = (
|
|
|
48
48
|
) => T;
|
|
49
49
|
|
|
50
50
|
|
|
51
|
-
const languageBaseLookupFor = (languageBases: ILanguageBase[]) =>
|
|
52
|
-
(language: Language) => {
|
|
53
|
-
const languageBase = languageBases.find((languageBase) => languageBase.language === language);
|
|
54
|
-
if (languageBase === undefined) {
|
|
55
|
-
throw new Error(`language ${language.name} (with key=${language.key} and version=${language.version}) not known`);
|
|
56
|
-
}
|
|
57
|
-
return languageBase;
|
|
58
|
-
};
|
|
59
|
-
|
|
60
|
-
const factoryLookupFor = (languageBases: ILanguageBase[], receiveDelta?: DeltaReceiver) => {
|
|
61
|
-
const lookup = languageBaseLookupFor(languageBases);
|
|
62
|
-
return (language: Language) => lookup(language).factory(receiveDelta);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
|
|
66
51
|
/**
|
|
67
52
|
* A quasi-tuple of the roots (of type {@link INodeBase}) of a model,
|
|
68
53
|
* and its {@link IdMapping} instance.
|
|
@@ -78,8 +63,7 @@ export type RootsWithIdMapping = { roots: INodeBase[], idMapping: IdMapping };
|
|
|
78
63
|
export const nodeBaseDeserializerWithIdMapping = (languageBases: ILanguageBase[], receiveDelta?: DeltaReceiver): Deserializer<RootsWithIdMapping> => {
|
|
79
64
|
|
|
80
65
|
const symbolTable = new MemoisingSymbolTable(languageBases.map(({language}) => language));
|
|
81
|
-
const languageBaseFor =
|
|
82
|
-
const factoryFor = factoryLookupFor(languageBases, receiveDelta);
|
|
66
|
+
const languageBaseFor = combinedLanguageBaseLookupFor(languageBases);
|
|
83
67
|
|
|
84
68
|
return (
|
|
85
69
|
serializationChunk: LionWebJsonChunk,
|
|
@@ -98,7 +82,7 @@ export const nodeBaseDeserializerWithIdMapping = (languageBases: ILanguageBase[]
|
|
|
98
82
|
return undefined;
|
|
99
83
|
}
|
|
100
84
|
|
|
101
|
-
const node =
|
|
85
|
+
const node = languageBaseFor(classifier.language).factory(receiveDelta)(classifier, id);
|
|
102
86
|
|
|
103
87
|
properties.forEach(({property: propertyMetaPointer, value}) => {
|
|
104
88
|
const feature = symbolTable.featureMatching(classifierMetaPointer, propertyMetaPointer);
|
package/src/factory.ts
CHANGED
|
@@ -15,35 +15,49 @@
|
|
|
15
15
|
// SPDX-FileCopyrightText: 2025 TRUMPF Laser SE and other contributors
|
|
16
16
|
// SPDX-License-Identifier: Apache-2.0
|
|
17
17
|
|
|
18
|
+
import { Language } from "@lionweb/core"
|
|
18
19
|
import { lazyMapGet } from "@lionweb/ts-utils"
|
|
19
20
|
import { ILanguageBase, NodeBaseFactory } from "./base-types.js"
|
|
20
21
|
import { DeltaReceiver } from "./deltas/index.js"
|
|
21
22
|
|
|
23
|
+
|
|
22
24
|
/**
|
|
23
|
-
* @return a {@link
|
|
25
|
+
* @return a function that looks up the {@link ILanguageBase language base} for the {@link Language language} passed to it,
|
|
26
|
+
* from among the given language bases.
|
|
27
|
+
* The returned function throws when the language wasn't among the languages the given bases were for.
|
|
28
|
+
* The lookup is hashmap-backed, so efficient.
|
|
24
29
|
*/
|
|
25
|
-
export const
|
|
30
|
+
export const combinedLanguageBaseLookupFor = (languageBases: ILanguageBase[]): ((language: Language) => ILanguageBase) => {
|
|
26
31
|
// create lookup map:
|
|
27
|
-
const
|
|
32
|
+
const languageKey2version2base: { [key: string]: { [version: string]: ILanguageBase } } = {}
|
|
28
33
|
languageBases.forEach((languageBase) => {
|
|
29
34
|
const {key, version} = languageBase.language
|
|
30
|
-
const
|
|
31
|
-
lazyMapGet(
|
|
32
|
-
// (Note: don't destructure factory from languageBase, as that will unbind it as "this"!)
|
|
35
|
+
const version2base = lazyMapGet(languageKey2version2base, key, () => ({}))
|
|
36
|
+
lazyMapGet(version2base, version, () => languageBase)
|
|
33
37
|
})
|
|
34
38
|
|
|
35
|
-
return (
|
|
36
|
-
const {key, version, name} =
|
|
37
|
-
const
|
|
38
|
-
if (
|
|
39
|
-
throw new Error(`language ${name} with key=${key} not
|
|
39
|
+
return (language) => {
|
|
40
|
+
const {key, version, name} = language
|
|
41
|
+
const version2base = languageKey2version2base[key]
|
|
42
|
+
if (version2base === undefined) {
|
|
43
|
+
throw new Error(`language ${name} with key=${key} not registered`)
|
|
40
44
|
}
|
|
41
|
-
const
|
|
42
|
-
if (
|
|
43
|
-
const candidateVersions = Object.keys(
|
|
44
|
-
throw new Error(`language ${name} with key=${key} and version=${version} not
|
|
45
|
+
const base = version2base[version]
|
|
46
|
+
if (base === undefined) {
|
|
47
|
+
const candidateVersions = Object.keys(version2base)
|
|
48
|
+
throw new Error(`language ${name} with key=${key} and version=${version} not registered${candidateVersions.length > 0 ? `- candidate version${candidateVersions.length > 1 ? `s` : ``}: ${candidateVersions.join(", ")}` : ``}`)
|
|
45
49
|
}
|
|
46
|
-
return
|
|
50
|
+
return base
|
|
47
51
|
}
|
|
48
52
|
}
|
|
49
53
|
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* @return a {@link NodeBaseFactory factory function} that works for all given {@link ILanguageBase language bases}.
|
|
57
|
+
*/
|
|
58
|
+
export const combinedFactoryFor = (languageBases: ILanguageBase[], receiveDelta?: DeltaReceiver): NodeBaseFactory => {
|
|
59
|
+
const baseOf = combinedLanguageBaseLookupFor(languageBases)
|
|
60
|
+
return (classifier, id) =>
|
|
61
|
+
baseOf(classifier.language).factory(receiveDelta)(classifier, id)
|
|
62
|
+
}
|
|
63
|
+
|
package/src/id-mapping.ts
CHANGED
|
@@ -30,35 +30,56 @@ type NodesById = { [id: LionWebId]: INodeBase }
|
|
|
30
30
|
*/
|
|
31
31
|
export class IdMapping {
|
|
32
32
|
|
|
33
|
-
nodesById: NodesById;
|
|
33
|
+
private nodesById: NodesById;
|
|
34
34
|
constructor(nodesById: NodesById) {
|
|
35
35
|
this.nodesById = {...nodesById};
|
|
36
36
|
}
|
|
37
37
|
// TODO consider using an instance of Map<Id, INodeBase> instead
|
|
38
38
|
|
|
39
|
-
|
|
39
|
+
/**
|
|
40
|
+
* @return the {@link INodeBase node} with the given {@link LionWebId `id`}, or
|
|
41
|
+
* @throws an Error if no node with the given ID was registered.
|
|
42
|
+
*/
|
|
43
|
+
fromId = (id: LionWebId): INodeBase => {
|
|
40
44
|
if (!(id in this.nodesById)) {
|
|
41
45
|
throw new Error(`node with id=${id} not in ID mapping`);
|
|
42
46
|
}
|
|
43
47
|
return this.nodesById[id];
|
|
44
48
|
}
|
|
45
49
|
|
|
50
|
+
/**
|
|
51
|
+
* @return the {@link INodeBase node} with the given {@link LionWebId `id`},
|
|
52
|
+
* or `undefined` if no node with the given ID was registered.
|
|
53
|
+
*/
|
|
46
54
|
tryFromId = (id: LionWebId): (INodeBase | undefined) =>
|
|
47
55
|
this.nodesById[id];
|
|
48
56
|
|
|
57
|
+
/**
|
|
58
|
+
* @return the {@link INodeBase node} referenced from the given {@link LionWebId ID},
|
|
59
|
+
* or `unresolved` if `unresolved` was passed in or no node with the given ID was registered.
|
|
60
|
+
*/
|
|
49
61
|
fromRefId = (idOrUnresolved: IdOrUnresolved): SingleRef<INodeBase> =>
|
|
50
|
-
idOrUnresolved ===
|
|
51
|
-
?
|
|
62
|
+
idOrUnresolved === unresolved
|
|
63
|
+
? unresolved
|
|
52
64
|
: (this.nodesById[idOrUnresolved] ?? unresolved);
|
|
53
65
|
|
|
54
66
|
/**
|
|
55
67
|
* Updates this {@link IdMapping} with the given `node` *and all its descendants* (recursively).
|
|
56
68
|
*/
|
|
57
|
-
updateWith(node: INodeBase) {
|
|
69
|
+
updateWith= (node: INodeBase) => {
|
|
58
70
|
this.nodesById[node.id] = node;
|
|
59
71
|
node.children // recurse into all children
|
|
60
72
|
.forEach((child) => this.updateWith(child));
|
|
61
73
|
}
|
|
62
74
|
|
|
75
|
+
/**
|
|
76
|
+
* Re-initializes this {@link IdMapping ID mapping} with the given nodes-by-ID.
|
|
77
|
+
* This completely removes all registrations of nodes,
|
|
78
|
+
* and should only be used by components which are in complete control of the nodes being passed to this method.
|
|
79
|
+
*/
|
|
80
|
+
reinitializeWith = (nodesById: NodesById) => {
|
|
81
|
+
this.nodesById = nodesById
|
|
82
|
+
}
|
|
83
|
+
|
|
63
84
|
}
|
|
64
85
|
|
package/src/textualizer.ts
CHANGED
|
@@ -54,7 +54,7 @@ export const asTreeTextWith = (identificationFor: (node: INodeBase) => string):
|
|
|
54
54
|
const valueManager = node.getPropertyValueManager(feature)
|
|
55
55
|
const displayValue = (() => {
|
|
56
56
|
if (!valueManager.isSet()) {
|
|
57
|
-
return
|
|
57
|
+
return `<not set>`
|
|
58
58
|
}
|
|
59
59
|
const value = valueManager.getDirectly()
|
|
60
60
|
if (feature.type === LionCore_builtinsBase.INSTANCE.String) {
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
|
|
18
18
|
import { action, observable } from "mobx"
|
|
19
19
|
|
|
20
|
-
import { INodeBase
|
|
20
|
+
import { INodeBase } from "../base-types.js"
|
|
21
21
|
import { checkIndex, ValueManager } from "./base.js"
|
|
22
22
|
import {
|
|
23
23
|
AnnotationAddedDelta,
|
|
@@ -67,7 +67,7 @@ export class AnnotationsValueManager extends ValueManager {
|
|
|
67
67
|
newAnnotation.attachTo(this.container, null);
|
|
68
68
|
return false;
|
|
69
69
|
} else {
|
|
70
|
-
const oldIndex =
|
|
70
|
+
const oldIndex = oldParent.annotationsValueManager.removeDirectly(newAnnotation);
|
|
71
71
|
newAnnotation.attachTo(this.container, null);
|
|
72
72
|
return [oldParent, oldIndex];
|
|
73
73
|
}
|