@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.
Files changed (56) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/dist/deserializer.d.ts.map +1 -1
  3. package/dist/deserializer.js +27 -22
  4. package/dist/deserializer.js.map +1 -1
  5. package/dist/functions.d.ts +2 -3
  6. package/dist/functions.d.ts.map +1 -1
  7. package/dist/functions.js +2 -3
  8. package/dist/functions.js.map +1 -1
  9. package/dist/m1/reference-utils.d.ts.map +1 -1
  10. package/dist/m1/reference-utils.js +0 -1
  11. package/dist/m1/reference-utils.js.map +1 -1
  12. package/dist/m3/builtins-common.js +3 -3
  13. package/dist/m3/builtins-common.js.map +1 -1
  14. package/dist/m3/constraints.d.ts +5 -0
  15. package/dist/m3/constraints.d.ts.map +1 -1
  16. package/dist/m3/constraints.js +1 -1
  17. package/dist/m3/constraints.js.map +1 -1
  18. package/dist/m3/factory.d.ts +2 -2
  19. package/dist/m3/factory.d.ts.map +1 -1
  20. package/dist/m3/factory.js.map +1 -1
  21. package/dist/m3/functions.d.ts.map +1 -1
  22. package/dist/m3/functions.js +2 -2
  23. package/dist/m3/functions.js.map +1 -1
  24. package/dist/m3/types.d.ts +6 -2
  25. package/dist/m3/types.d.ts.map +1 -1
  26. package/dist/m3/types.js +10 -5
  27. package/dist/m3/types.js.map +1 -1
  28. package/dist/m3/versions/v2023_1/builtins-legacy.js +3 -3
  29. package/dist/m3/versions/v2023_1/builtins-legacy.js.map +1 -1
  30. package/dist/m3/versions/v2023_1/builtins.d.ts.map +1 -1
  31. package/dist/m3/versions/v2023_1/builtins.js +2 -1
  32. package/dist/m3/versions/v2023_1/builtins.js.map +1 -1
  33. package/dist/m3/versions/v2023_1/lioncore.d.ts.map +1 -1
  34. package/dist/m3/versions/v2023_1/lioncore.js +16 -15
  35. package/dist/m3/versions/v2023_1/lioncore.js.map +1 -1
  36. package/dist/references.d.ts +31 -8
  37. package/dist/references.d.ts.map +1 -1
  38. package/dist/references.js +41 -6
  39. package/dist/references.js.map +1 -1
  40. package/dist/serializer.d.ts.map +1 -1
  41. package/dist/serializer.js +23 -9
  42. package/dist/serializer.js.map +1 -1
  43. package/package.json +3 -3
  44. package/src/deserializer.ts +30 -27
  45. package/src/functions.ts +3 -4
  46. package/src/m1/reference-utils.ts +0 -1
  47. package/src/m3/builtins-common.ts +3 -3
  48. package/src/m3/constraints.ts +1 -1
  49. package/src/m3/factory.ts +10 -2
  50. package/src/m3/functions.ts +9 -3
  51. package/src/m3/types.ts +11 -5
  52. package/src/m3/versions/v2023_1/builtins-legacy.ts +3 -3
  53. package/src/m3/versions/v2023_1/builtins.ts +2 -1
  54. package/src/m3/versions/v2023_1/lioncore.ts +16 -15
  55. package/src/references.ts +46 -11
  56. 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(this.language, name, this.key(this.language.name, name), this.id(this.language.name, name), abstract, extends_)
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
  }
@@ -4,7 +4,13 @@
4
4
 
5
5
 
6
6
  import { LionWebId, LionWebKey } from "@lionweb/json"
7
- import { cycleWith, flatMapNonCyclingFollowing, sortByStringKey } from "@lionweb/ts-utils"
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
- sortByStringKey(ts, nameOf)
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) as 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() // (reference)
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() // (reference)
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() // (reference)
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 { isUnresolvedReference } from "../../../references.js"
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 (isUnresolvedReference(type)) {
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 (isUnresolvedReference(type)) {
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", true)
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", true).implementing(ikeyed)
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", false, feature)
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", true, feature)
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", false, link)
41
+ const containment = factory.concept("Containment", ConceptModifier.concrete, link)
41
42
 
42
- const reference = factory.concept("Reference", false, link)
43
+ const reference = factory.concept("Reference", ConceptModifier.concrete, link)
43
44
 
44
- const languageEntity = factory.concept("LanguageEntity", true).implementing(ikeyed)
45
+ const languageEntity = factory.concept("LanguageEntity", ConceptModifier.abstract).implementing(ikeyed)
45
46
 
46
- const classifier = factory.concept("Classifier", true, languageEntity)
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", false, classifier)
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", false, classifier)
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", false, classifier)
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", true, languageEntity)
68
+ const dataType = factory.concept("DataType", ConceptModifier.abstract, languageEntity)
68
69
  property_type.ofType(dataType)
69
70
 
70
- const primitiveType = factory.concept("PrimitiveType", false, dataType)
71
+ const primitiveType = factory.concept("PrimitiveType", ConceptModifier.concrete, dataType)
71
72
 
72
- const enumeration = factory.concept("Enumeration", false, dataType)
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", false).implementing(ikeyed)
75
+ const enumerationLiteral = factory.concept("EnumerationLiteral", ConceptModifier.concrete).implementing(ikeyed)
75
76
  enumeration_literals.ofType(enumerationLiteral)
76
77
 
77
- const language = factory.concept("Language", false).implementing(ikeyed).isPartition()
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
- * Type for unresolved references.
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 type UnresolvedReference = typeof unresolved
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
- * @return a value of {@link UnresolvedReference} that’s a placeholder for a yet-to-set reference.
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 a given (at most) single-valued reference actually refers to something.
46
+ * @return whether the given {@link UnresolvedReference} corresponds to an (explicitly-)unset (yet-to-set) reference.
31
47
  */
32
- export const isRef = <NT extends Node>(ref?: SingleRef<NT>): ref is NT =>
33
- ref !== undefined && ref !== unresolved
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 === unresolved
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(asIds(children))
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
- // Note: value can be null === typeof unresolved, e.g. on an unset (or previously unresolved) single-valued reference
221
- const targets = asArray(value) as (RT | null)[]
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: keepDefineds(targets) // (skip "non-connected" targets)
228
- .map(t => ({
229
- resolveInfo:
230
- (reader.resolveInfoFor ? reader.resolveInfoFor(t, feature) : simpleNameDeducer(t, feature)) ?? null,
231
- reference: t.id
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
  }