@lionweb/core 0.10.0-beta.0 → 0.10.0-beta.1
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 +13 -0
- package/dist/deserializer.d.ts.map +1 -1
- package/dist/deserializer.js +27 -22
- package/dist/deserializer.js.map +1 -1
- package/dist/functions.d.ts +2 -3
- package/dist/functions.d.ts.map +1 -1
- package/dist/functions.js +2 -3
- package/dist/functions.js.map +1 -1
- package/dist/m1/reference-utils.d.ts.map +1 -1
- package/dist/m1/reference-utils.js +0 -1
- package/dist/m1/reference-utils.js.map +1 -1
- package/dist/m3/builtins-common.js +3 -3
- package/dist/m3/builtins-common.js.map +1 -1
- package/dist/m3/constraints.d.ts +5 -0
- package/dist/m3/constraints.d.ts.map +1 -1
- package/dist/m3/constraints.js +1 -1
- package/dist/m3/constraints.js.map +1 -1
- package/dist/m3/factory.d.ts +2 -2
- package/dist/m3/factory.d.ts.map +1 -1
- package/dist/m3/factory.js.map +1 -1
- package/dist/m3/functions.d.ts.map +1 -1
- package/dist/m3/functions.js +2 -2
- package/dist/m3/functions.js.map +1 -1
- package/dist/m3/types.d.ts +6 -2
- package/dist/m3/types.d.ts.map +1 -1
- package/dist/m3/types.js +10 -5
- package/dist/m3/types.js.map +1 -1
- package/dist/m3/versions/v2023_1/builtins-legacy.js +3 -3
- package/dist/m3/versions/v2023_1/builtins-legacy.js.map +1 -1
- package/dist/m3/versions/v2023_1/builtins.d.ts.map +1 -1
- package/dist/m3/versions/v2023_1/builtins.js +2 -1
- package/dist/m3/versions/v2023_1/builtins.js.map +1 -1
- package/dist/m3/versions/v2023_1/lioncore.d.ts.map +1 -1
- package/dist/m3/versions/v2023_1/lioncore.js +16 -15
- package/dist/m3/versions/v2023_1/lioncore.js.map +1 -1
- package/dist/references.d.ts +31 -8
- package/dist/references.d.ts.map +1 -1
- package/dist/references.js +41 -6
- package/dist/references.js.map +1 -1
- package/dist/serializer.d.ts.map +1 -1
- package/dist/serializer.js +23 -9
- package/dist/serializer.js.map +1 -1
- package/package.json +3 -3
- package/src/deserializer.ts +30 -27
- package/src/functions.ts +3 -4
- package/src/m1/reference-utils.ts +0 -1
- package/src/m3/builtins-common.ts +3 -3
- package/src/m3/constraints.ts +1 -1
- package/src/m3/factory.ts +10 -2
- package/src/m3/functions.ts +9 -3
- package/src/m3/types.ts +11 -5
- package/src/m3/versions/v2023_1/builtins-legacy.ts +3 -3
- package/src/m3/versions/v2023_1/builtins.ts +2 -1
- package/src/m3/versions/v2023_1/lioncore.ts +16 -15
- package/src/references.ts +46 -11
- package/src/serializer.ts +26 -11
package/src/m3/factory.ts
CHANGED
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
Annotation,
|
|
5
5
|
Classifier,
|
|
6
6
|
Concept,
|
|
7
|
+
ConceptModifier,
|
|
7
8
|
Containment,
|
|
8
9
|
Enumeration,
|
|
9
10
|
EnumerationLiteral,
|
|
@@ -44,8 +45,15 @@ export class LanguageFactory {
|
|
|
44
45
|
return annotation
|
|
45
46
|
}
|
|
46
47
|
|
|
47
|
-
concept(name: string, abstract: boolean, extends_?: SingleRef<Concept>): Concept {
|
|
48
|
-
const concept = new Concept(
|
|
48
|
+
concept(name: string, abstract: boolean | ConceptModifier, extends_?: SingleRef<Concept>): Concept {
|
|
49
|
+
const concept = new Concept(
|
|
50
|
+
this.language,
|
|
51
|
+
name,
|
|
52
|
+
this.key(this.language.name, name),
|
|
53
|
+
this.id(this.language.name, name),
|
|
54
|
+
abstract,
|
|
55
|
+
extends_
|
|
56
|
+
)
|
|
49
57
|
this.language.havingEntities(concept)
|
|
50
58
|
return concept
|
|
51
59
|
}
|
package/src/m3/functions.ts
CHANGED
|
@@ -4,7 +4,13 @@
|
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
import { LionWebId, LionWebKey } from "@lionweb/json"
|
|
7
|
-
import {
|
|
7
|
+
import {
|
|
8
|
+
cycleWith,
|
|
9
|
+
flatMapNonCyclingFollowing,
|
|
10
|
+
mappedComparer,
|
|
11
|
+
regularStringComparer,
|
|
12
|
+
sorterWith
|
|
13
|
+
} from "@lionweb/ts-utils"
|
|
8
14
|
import { containmentChain } from "../functions.js"
|
|
9
15
|
import { ClassifierDeducer } from "../reading.js"
|
|
10
16
|
import { isRef, UnresolvedReference } from "../references.js"
|
|
@@ -156,7 +162,7 @@ const nameOf = <T extends INamed>({name}: T): string =>
|
|
|
156
162
|
* @return the given named things sorted by name
|
|
157
163
|
*/
|
|
158
164
|
export const nameSorted = <T extends INamed>(ts: T[]): T[] =>
|
|
159
|
-
|
|
165
|
+
sorterWith<T>(mappedComparer(nameOf, regularStringComparer))(ts)
|
|
160
166
|
|
|
161
167
|
|
|
162
168
|
/**
|
|
@@ -303,7 +309,7 @@ const metaTypedBasedClassifierDeducerFor = <NT extends Node & IMetaTyped>(langua
|
|
|
303
309
|
* @return all {@link Concept concepts} defined in the given {@link Language language}.
|
|
304
310
|
*/
|
|
305
311
|
const conceptsOf = (language: Language): Concept[] =>
|
|
306
|
-
language.entities.filter((entity) => entity instanceof Concept)
|
|
312
|
+
language.entities.filter((entity) => entity instanceof Concept)
|
|
307
313
|
|
|
308
314
|
|
|
309
315
|
const isInstantiableClassifier = (entity: LanguageEntity): boolean =>
|
package/src/m3/types.ts
CHANGED
|
@@ -88,7 +88,7 @@ class Property extends Feature {
|
|
|
88
88
|
metaType(): string {
|
|
89
89
|
return "Property"
|
|
90
90
|
}
|
|
91
|
-
type: SingleRef<DataType> = referenceToSet
|
|
91
|
+
type: SingleRef<DataType> = referenceToSet // (reference)
|
|
92
92
|
ofType(type: DataType): Property {
|
|
93
93
|
this.type = type
|
|
94
94
|
return this
|
|
@@ -97,7 +97,7 @@ class Property extends Feature {
|
|
|
97
97
|
|
|
98
98
|
abstract class Link extends Feature {
|
|
99
99
|
multiple /*: boolean */ = false
|
|
100
|
-
type: SingleRef<Classifier> = referenceToSet
|
|
100
|
+
type: SingleRef<Classifier> = referenceToSet // (reference)
|
|
101
101
|
isMultiple() {
|
|
102
102
|
this.multiple = true
|
|
103
103
|
return this
|
|
@@ -145,6 +145,11 @@ abstract class Classifier extends LanguageEntity {
|
|
|
145
145
|
}
|
|
146
146
|
}
|
|
147
147
|
|
|
148
|
+
enum ConceptModifier {
|
|
149
|
+
concrete,
|
|
150
|
+
abstract
|
|
151
|
+
}
|
|
152
|
+
|
|
148
153
|
class Concept extends Classifier {
|
|
149
154
|
metaType(): string {
|
|
150
155
|
return "Concept"
|
|
@@ -153,9 +158,9 @@ class Concept extends Classifier {
|
|
|
153
158
|
partition: boolean
|
|
154
159
|
extends?: SingleRef<Concept> // (reference)
|
|
155
160
|
readonly implements: MultiRef<Interface> = [] // (reference)
|
|
156
|
-
constructor(language: Language, name: string, key: LionWebKey, id: LionWebId, abstract: boolean, extends_?: SingleRef<Concept>) {
|
|
161
|
+
constructor(language: Language, name: string, key: LionWebKey, id: LionWebId, abstract: boolean | ConceptModifier, extends_?: SingleRef<Concept>) {
|
|
157
162
|
super(language, name, key, id)
|
|
158
|
-
this.abstract = abstract
|
|
163
|
+
this.abstract = abstract === ConceptModifier.abstract || abstract === true
|
|
159
164
|
this.extends = extends_
|
|
160
165
|
this.partition = false
|
|
161
166
|
}
|
|
@@ -176,7 +181,7 @@ class Annotation extends Classifier {
|
|
|
176
181
|
}
|
|
177
182
|
extends?: SingleRef<Annotation> // (reference)
|
|
178
183
|
readonly implements: MultiRef<Interface> = [] // (reference)
|
|
179
|
-
annotates: SingleRef<Classifier> = referenceToSet
|
|
184
|
+
annotates: SingleRef<Classifier> = referenceToSet // (reference)
|
|
180
185
|
constructor(language: Language, name: string, key: LionWebKey, id: LionWebId, extends_?: SingleRef<Annotation>) {
|
|
181
186
|
super(language, name, key, id)
|
|
182
187
|
this.extends = extends_
|
|
@@ -291,6 +296,7 @@ export {
|
|
|
291
296
|
Annotation,
|
|
292
297
|
Classifier,
|
|
293
298
|
Concept,
|
|
299
|
+
ConceptModifier,
|
|
294
300
|
Containment,
|
|
295
301
|
DataType,
|
|
296
302
|
Datatype,
|
|
@@ -2,7 +2,7 @@ import { asMinimalJsonString } from "@lionweb/ts-utils"
|
|
|
2
2
|
import { shouldBeIdentical } from "../../builtins-common.js"
|
|
3
3
|
import { DataType, Property } from "../../types.js"
|
|
4
4
|
import { PropertyValueDeserializer } from "../../../deserializer.js"
|
|
5
|
-
import {
|
|
5
|
+
import { isRef } from "../../../references.js"
|
|
6
6
|
import { PropertyValueSerializer } from "../../../serializer.js"
|
|
7
7
|
import { v2023_1 } from "./version.js"
|
|
8
8
|
|
|
@@ -62,7 +62,7 @@ export class BuiltinPropertyValueDeserializer
|
|
|
62
62
|
throw new Error(`can't deserialize undefined as the value of required property "${property.name}" (on classifier "${property.classifier.name}" in language "${property.classifier.language.name}")`)
|
|
63
63
|
}
|
|
64
64
|
const { type } = property
|
|
65
|
-
if (
|
|
65
|
+
if (!isRef(type)) {
|
|
66
66
|
throw new Error(`can't deserialize property "${property.name}" (on classifier "${property.classifier.name}" in language "${property.classifier.language.name}") with unspecified type`)
|
|
67
67
|
}
|
|
68
68
|
const specificDeserializer = this.byType(type)
|
|
@@ -104,7 +104,7 @@ export class BuiltinPropertyValueSerializer extends DataTypeRegistry<(value: unk
|
|
|
104
104
|
throw new Error(`can't serialize undefined as the value of required property "${property.name}" (on classifier "${property.classifier.name}" in language "${property.classifier.language.name}")`)
|
|
105
105
|
}
|
|
106
106
|
const { type } = property
|
|
107
|
-
if (
|
|
107
|
+
if (!isRef(type)) {
|
|
108
108
|
throw new Error(`can't serialize property "${property.name}" (on classifier "${property.classifier.name}" in language "${property.classifier.language.name}") with unspecified type`)
|
|
109
109
|
}
|
|
110
110
|
const specificSerializer = this.byType(type)
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
} from "../../builtins-common.js"
|
|
10
10
|
import { isBuiltinNodeConcept } from "../../builtins-function.js"
|
|
11
11
|
import { LanguageFactory } from "../../factory.js"
|
|
12
|
+
import { ConceptModifier } from "../../types.js"
|
|
12
13
|
|
|
13
14
|
|
|
14
15
|
const factory = new LanguageFactory(
|
|
@@ -27,7 +28,7 @@ const booleanDataType = factory.primitiveType("Boolean")
|
|
|
27
28
|
const integerDataType = factory.primitiveType("Integer")
|
|
28
29
|
const jsonDataType = factory.primitiveType("JSON")
|
|
29
30
|
|
|
30
|
-
const node = factory.concept("Node",
|
|
31
|
+
const node = factory.concept("Node", ConceptModifier.abstract)
|
|
31
32
|
|
|
32
33
|
const inamed = factory.interface("INamed")
|
|
33
34
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { lioncoreBuiltinsFacade } from "./builtins.js"
|
|
2
2
|
import { LanguageFactory } from "../../factory.js"
|
|
3
3
|
import { generatedLionCoreKeyFrom, LionCoreFacade } from "../../lioncore-common.js"
|
|
4
|
+
import { ConceptModifier } from "../../types.js"
|
|
4
5
|
|
|
5
6
|
|
|
6
7
|
const factory = new LanguageFactory(
|
|
@@ -27,54 +28,54 @@ const { booleanDataType, stringDataType } = lioncoreBuiltinsFacade.primitiveType
|
|
|
27
28
|
const ikeyed = factory.interface("IKeyed").extending(inamed)
|
|
28
29
|
const ikeyed_key = factory.property(ikeyed, "key").ofType(stringDataType)
|
|
29
30
|
|
|
30
|
-
const feature = factory.concept("Feature",
|
|
31
|
+
const feature = factory.concept("Feature", ConceptModifier.abstract).implementing(ikeyed)
|
|
31
32
|
factory.property(feature, "optional").ofType(booleanDataType)
|
|
32
33
|
|
|
33
|
-
const property = factory.concept("Property",
|
|
34
|
+
const property = factory.concept("Property", ConceptModifier.concrete, feature)
|
|
34
35
|
const property_type = factory.reference(property, "type")
|
|
35
36
|
|
|
36
|
-
const link = factory.concept("Link",
|
|
37
|
+
const link = factory.concept("Link", ConceptModifier.abstract, feature)
|
|
37
38
|
factory.property(link, "multiple").ofType(booleanDataType)
|
|
38
39
|
const link_type = factory.reference(link, "type")
|
|
39
40
|
|
|
40
|
-
const containment = factory.concept("Containment",
|
|
41
|
+
const containment = factory.concept("Containment", ConceptModifier.concrete, link)
|
|
41
42
|
|
|
42
|
-
const reference = factory.concept("Reference",
|
|
43
|
+
const reference = factory.concept("Reference", ConceptModifier.concrete, link)
|
|
43
44
|
|
|
44
|
-
const languageEntity = factory.concept("LanguageEntity",
|
|
45
|
+
const languageEntity = factory.concept("LanguageEntity", ConceptModifier.abstract).implementing(ikeyed)
|
|
45
46
|
|
|
46
|
-
const classifier = factory.concept("Classifier",
|
|
47
|
+
const classifier = factory.concept("Classifier", ConceptModifier.abstract, languageEntity)
|
|
47
48
|
factory.containment(classifier, "features").isOptional().isMultiple().ofType(feature)
|
|
48
49
|
link_type.ofType(classifier)
|
|
49
50
|
|
|
50
|
-
const annotation = factory.concept("Annotation",
|
|
51
|
+
const annotation = factory.concept("Annotation", ConceptModifier.concrete, classifier)
|
|
51
52
|
factory.reference(annotation, "annotates").isOptional().ofType(classifier)
|
|
52
53
|
factory.reference(annotation, "extends").isOptional().ofType(annotation)
|
|
53
54
|
const annotation_implements = factory.reference(annotation, "implements").isMultiple().isOptional()
|
|
54
55
|
|
|
55
|
-
const concept = factory.concept("Concept",
|
|
56
|
+
const concept = factory.concept("Concept", ConceptModifier.concrete, classifier)
|
|
56
57
|
const concept_abstract = factory.property(concept, "abstract").ofType(booleanDataType)
|
|
57
58
|
factory.property(concept, "partition").ofType(booleanDataType)
|
|
58
59
|
factory.reference(concept, "extends").isOptional().ofType(concept)
|
|
59
60
|
const concept_implements = factory.reference(concept, "implements").isOptional().isMultiple()
|
|
60
61
|
|
|
61
|
-
const interface_ = factory.concept("Interface",
|
|
62
|
+
const interface_ = factory.concept("Interface", ConceptModifier.concrete, classifier)
|
|
62
63
|
factory.reference(interface_, "extends").isOptional().isMultiple().ofType(interface_)
|
|
63
64
|
|
|
64
65
|
annotation_implements.ofType(interface_)
|
|
65
66
|
concept_implements.ofType(interface_)
|
|
66
67
|
|
|
67
|
-
const dataType = factory.concept("DataType",
|
|
68
|
+
const dataType = factory.concept("DataType", ConceptModifier.abstract, languageEntity)
|
|
68
69
|
property_type.ofType(dataType)
|
|
69
70
|
|
|
70
|
-
const primitiveType = factory.concept("PrimitiveType",
|
|
71
|
+
const primitiveType = factory.concept("PrimitiveType", ConceptModifier.concrete, dataType)
|
|
71
72
|
|
|
72
|
-
const enumeration = factory.concept("Enumeration",
|
|
73
|
+
const enumeration = factory.concept("Enumeration", ConceptModifier.concrete, dataType)
|
|
73
74
|
const enumeration_literals = factory.containment(enumeration, "literals").isMultiple().isOptional()
|
|
74
|
-
const enumerationLiteral = factory.concept("EnumerationLiteral",
|
|
75
|
+
const enumerationLiteral = factory.concept("EnumerationLiteral", ConceptModifier.concrete).implementing(ikeyed)
|
|
75
76
|
enumeration_literals.ofType(enumerationLiteral)
|
|
76
77
|
|
|
77
|
-
const language = factory.concept("Language",
|
|
78
|
+
const language = factory.concept("Language", ConceptModifier.concrete).implementing(ikeyed).isPartition()
|
|
78
79
|
const language_version = factory.property(language, "version").ofType(stringDataType)
|
|
79
80
|
factory.containment(language, "entities").isOptional().isMultiple().ofType(languageEntity)
|
|
80
81
|
factory.reference(language, "dependsOn").isOptional().isMultiple().ofType(language)
|
package/src/references.ts
CHANGED
|
@@ -1,42 +1,77 @@
|
|
|
1
|
+
import { LionWebId } from "@lionweb/json"
|
|
2
|
+
import { stringifyPropertiesOf } from "@lionweb/ts-utils"
|
|
3
|
+
|
|
1
4
|
import { Node } from "./types.js"
|
|
5
|
+
import { INamed } from "./m3/index.js"
|
|
2
6
|
|
|
3
7
|
|
|
4
8
|
/**
|
|
5
|
-
* The `unresolved` symbol indicates a reference value which hasn't been resolved yet.
|
|
9
|
+
* The `unresolved` “symbol” indicates a reference value which hasn't been resolved yet.
|
|
6
10
|
* It differs from an unset (`undefined`) value.
|
|
7
11
|
* This value shouldn’t be manipulated/compared to directly!
|
|
12
|
+
*
|
|
13
|
+
* @deprecated Use {@link referenceToSet} or {@link UnresolvedReference} instead.
|
|
8
14
|
*/
|
|
9
15
|
export const unresolved = null
|
|
10
16
|
|
|
17
|
+
|
|
11
18
|
/**
|
|
12
|
-
*
|
|
19
|
+
* Representation of an unresolved reference.
|
|
20
|
+
* At most one of `targetId` or `resolveInfo` can be `undefined`.
|
|
21
|
+
*
|
|
22
|
+
* *Note* that this instance will **not** exhibit object equality,
|
|
23
|
+
* i.e.: the resolved target of an unresolved reference will be a different object!
|
|
13
24
|
*/
|
|
14
|
-
export
|
|
25
|
+
export class UnresolvedReference {
|
|
26
|
+
constructor(public readonly targetId?: LionWebId, public resolveInfo?: string) {}
|
|
27
|
+
toString = () =>
|
|
28
|
+
`unresolved reference to target:` + stringifyPropertiesOf(this, "targetId", "resolveInfo")
|
|
29
|
+
}
|
|
15
30
|
|
|
16
31
|
/**
|
|
17
|
-
*
|
|
32
|
+
* A singleton representing an unset reference that’s meant to be set,
|
|
33
|
+
* distinguishing that from a reference that’s intentionally not set
|
|
34
|
+
* — which can only happen if that reference is (defined as) optional.
|
|
18
35
|
*/
|
|
19
|
-
export const referenceToSet = ()
|
|
20
|
-
unresolved
|
|
36
|
+
export const referenceToSet = Symbol("<unset reference>")
|
|
21
37
|
|
|
22
38
|
/**
|
|
23
39
|
* A type definition for a reference value that can be unresolved.
|
|
24
40
|
* Note: this type is primarily meant to be used to type nodes’ properties,
|
|
25
41
|
* but should be avoided as a return type for “auxiliary” functions.
|
|
26
42
|
*/
|
|
27
|
-
export type SingleRef<NT extends Node> = NT | UnresolvedReference
|
|
43
|
+
export type SingleRef<NT extends Node> = NT | UnresolvedReference | typeof referenceToSet
|
|
28
44
|
|
|
29
45
|
/**
|
|
30
|
-
* @return whether
|
|
46
|
+
* @return whether the given {@link UnresolvedReference} corresponds to an (explicitly-)unset (yet-to-set) reference.
|
|
31
47
|
*/
|
|
32
|
-
export const
|
|
33
|
-
ref
|
|
48
|
+
export const isReferenceToSet = <T extends Node>(ref?: SingleRef<T>): ref is typeof referenceToSet =>
|
|
49
|
+
ref === referenceToSet
|
|
34
50
|
|
|
35
51
|
/**
|
|
36
52
|
* Type function for the {@link UnresolvedReference} type.
|
|
37
53
|
*/
|
|
38
54
|
export const isUnresolvedReference = <NT extends Node>(ref?: SingleRef<NT>): ref is UnresolvedReference =>
|
|
39
|
-
ref
|
|
55
|
+
ref instanceof UnresolvedReference
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* @return whether a given (at most) single-valued reference actually refers to something.
|
|
59
|
+
*/
|
|
60
|
+
export const isRef = <NT extends Node>(ref?: SingleRef<NT>): ref is NT =>
|
|
61
|
+
ref !== undefined && !isReferenceToSet(ref) && !isUnresolvedReference(ref)
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* @return either the referenced node’s name, or the `resolveInfo` if the reference is unresolved, or `undefined`.
|
|
65
|
+
*/
|
|
66
|
+
export const tryToRenderAsText = <T extends Node & INamed>(ref?: SingleRef<T>): string | undefined => {
|
|
67
|
+
if (ref === undefined || isReferenceToSet(ref)) {
|
|
68
|
+
return undefined
|
|
69
|
+
}
|
|
70
|
+
if (isUnresolvedReference(ref)) {
|
|
71
|
+
return ref.resolveInfo
|
|
72
|
+
}
|
|
73
|
+
return ref.name
|
|
74
|
+
}
|
|
40
75
|
|
|
41
76
|
|
|
42
77
|
/**
|
package/src/serializer.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { LionWebId, LionWebJsonChunk, LionWebJsonNode } from "@lionweb/json"
|
|
1
|
+
import { LionWebId, LionWebJsonChunk, LionWebJsonNode, LionWebJsonReferenceTarget } from "@lionweb/json"
|
|
2
2
|
import { asArray, keepDefineds, lazyMapGet, Nested3Map, uniquesAmong } from "@lionweb/ts-utils"
|
|
3
3
|
import { asIds, metaPointerForFeature } from "./functions.js"
|
|
4
4
|
import { Reader } from "./reading.js"
|
|
5
|
+
import { isRef, isReferenceToSet, SingleRef, UnresolvedReference } from "./references.js"
|
|
5
6
|
import { Node } from "./types.js"
|
|
6
7
|
import { inheritsDirectlyFrom } from "./m3/functions.js"
|
|
7
8
|
import {
|
|
@@ -206,8 +207,7 @@ export const serializerWith = <NT extends Node, RT extends Node = NT>(configurat
|
|
|
206
207
|
}
|
|
207
208
|
serializedNode.containments.push({
|
|
208
209
|
containment: featureMetaPointer,
|
|
209
|
-
children: keepDefineds(
|
|
210
|
-
.map(childId => childId as string)
|
|
210
|
+
children: asIds(keepDefineds(children))
|
|
211
211
|
})
|
|
212
212
|
children.forEach(childOrNull => {
|
|
213
213
|
if (childOrNull !== null) {
|
|
@@ -217,19 +217,34 @@ export const serializerWith = <NT extends Node, RT extends Node = NT>(configurat
|
|
|
217
217
|
return
|
|
218
218
|
}
|
|
219
219
|
if (feature instanceof Reference) {
|
|
220
|
-
|
|
221
|
-
|
|
220
|
+
const targets = (asArray(value) as SingleRef<RT>[]).filter((ref) => {
|
|
221
|
+
if (isRef(ref)) {
|
|
222
|
+
return true // (1) ref is a node, having an ID
|
|
223
|
+
}
|
|
224
|
+
if (isReferenceToSet(ref)) {
|
|
225
|
+
return false
|
|
226
|
+
}
|
|
227
|
+
return ref.targetId !== undefined || ref.resolveInfo !== undefined // (2) not both are undefined
|
|
228
|
+
}) as (RT | UnresolvedReference)[]
|
|
222
229
|
if (targets.length === 0 && !serializeEmptyFeatures) {
|
|
223
230
|
return
|
|
224
231
|
}
|
|
225
232
|
serializedNode.references.push({
|
|
226
233
|
reference: featureMetaPointer,
|
|
227
|
-
targets:
|
|
228
|
-
.map(t =>
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
234
|
+
targets: targets
|
|
235
|
+
.map((t) =>
|
|
236
|
+
t instanceof UnresolvedReference
|
|
237
|
+
? {
|
|
238
|
+
resolveInfo: t.resolveInfo ?? null,
|
|
239
|
+
reference: t.targetId ?? null
|
|
240
|
+
// at least one of these will be non-null <== (2)
|
|
241
|
+
} as LionWebJsonReferenceTarget
|
|
242
|
+
: {
|
|
243
|
+
resolveInfo: (reader.resolveInfoFor ? reader.resolveInfoFor(t, feature) : simpleNameDeducer(t, feature)) ?? null,
|
|
244
|
+
reference: t.id
|
|
245
|
+
// reference will be a non-null string (~(1))
|
|
246
|
+
}
|
|
247
|
+
)
|
|
233
248
|
})
|
|
234
249
|
return
|
|
235
250
|
}
|