@lionweb/core 0.7.0-beta.2 → 0.7.0-beta.20

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 (76) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/dist/deserializer.d.ts +2 -2
  3. package/dist/deserializer.d.ts.map +1 -1
  4. package/dist/deserializer.js +7 -10
  5. package/dist/deserializer.js.map +1 -1
  6. package/dist/extraction.d.ts.map +1 -1
  7. package/dist/functions.d.ts.map +1 -1
  8. package/dist/handler.d.ts +1 -1
  9. package/dist/index.d.ts +0 -1
  10. package/dist/index.d.ts.map +1 -1
  11. package/dist/index.js +0 -1
  12. package/dist/index.js.map +1 -1
  13. package/dist/m1/reference-utils.d.ts +1 -1
  14. package/dist/m1/reference-utils.d.ts.map +1 -1
  15. package/dist/m3/builtins.d.ts.map +1 -1
  16. package/dist/m3/builtins.js +2 -1
  17. package/dist/m3/builtins.js.map +1 -1
  18. package/dist/m3/constraints.d.ts.map +1 -1
  19. package/dist/m3/constraints.js +2 -2
  20. package/dist/m3/constraints.js.map +1 -1
  21. package/dist/m3/deserializer.d.ts.map +1 -1
  22. package/dist/m3/feature-resolvers.d.ts +23 -0
  23. package/dist/m3/feature-resolvers.d.ts.map +1 -0
  24. package/dist/m3/feature-resolvers.js +32 -0
  25. package/dist/m3/feature-resolvers.js.map +1 -0
  26. package/dist/m3/functions.d.ts +17 -1
  27. package/dist/m3/functions.d.ts.map +1 -1
  28. package/dist/m3/functions.js +21 -5
  29. package/dist/m3/functions.js.map +1 -1
  30. package/dist/m3/index.d.ts +2 -0
  31. package/dist/m3/index.d.ts.map +1 -1
  32. package/dist/m3/index.js +2 -0
  33. package/dist/m3/index.js.map +1 -1
  34. package/dist/m3/reference-checker.d.ts.map +1 -1
  35. package/dist/m3/serializer.d.ts.map +1 -1
  36. package/dist/{symbol-table.d.ts → m3/symbol-table.d.ts} +9 -14
  37. package/dist/m3/symbol-table.d.ts.map +1 -0
  38. package/dist/m3/symbol-table.js +38 -0
  39. package/dist/m3/symbol-table.js.map +1 -0
  40. package/dist/m3/types.d.ts.map +1 -1
  41. package/dist/references.d.ts +1 -1
  42. package/dist/references.d.ts.map +1 -1
  43. package/dist/serializer.d.ts.map +1 -1
  44. package/dist/serializer.js +19 -9
  45. package/dist/serializer.js.map +1 -1
  46. package/package.json +31 -31
  47. package/src/deserializer.ts +224 -0
  48. package/src/dynamic-facade.ts +63 -0
  49. package/src/extraction.ts +31 -0
  50. package/src/functions.ts +28 -0
  51. package/src/handler.ts +57 -0
  52. package/src/index.ts +13 -0
  53. package/src/m1/reference-utils.ts +106 -0
  54. package/src/m3/README.md +16 -0
  55. package/src/m3/builtins.ts +170 -0
  56. package/src/m3/constraints.ts +109 -0
  57. package/src/m3/deserializer.ts +38 -0
  58. package/src/m3/facade.ts +130 -0
  59. package/src/m3/factory.ts +98 -0
  60. package/src/m3/feature-resolvers.ts +55 -0
  61. package/src/m3/functions.ts +379 -0
  62. package/src/m3/index.ts +12 -0
  63. package/src/m3/lioncore.ts +139 -0
  64. package/src/m3/reference-checker.ts +38 -0
  65. package/src/m3/serializer.ts +13 -0
  66. package/src/m3/symbol-table.ts +119 -0
  67. package/src/m3/types.ts +325 -0
  68. package/src/reading.ts +55 -0
  69. package/src/references.ts +31 -0
  70. package/src/serializer.ts +244 -0
  71. package/src/types.ts +11 -0
  72. package/src/version.ts +5 -0
  73. package/src/writing.ts +79 -0
  74. package/dist/symbol-table.d.ts.map +0 -1
  75. package/dist/symbol-table.js +0 -66
  76. package/dist/symbol-table.js.map +0 -1
@@ -0,0 +1,38 @@
1
+ import { SingleRef, unresolved } from "../references.js"
2
+ import { flatMap, qualifiedNameOf } from "./functions.js"
3
+ import { Concept, Containment, Language, Property, Reference } from "./types.js"
4
+
5
+
6
+ /**
7
+ * Checks whether the metamodel of the given language contains unresolved references.
8
+ */
9
+ export const checkReferences = (language: Language): string[] =>
10
+ flatMap(
11
+ language,
12
+ (thing) => {
13
+
14
+ const locations: string[] = []
15
+ const check = (ref: SingleRef<unknown>, location: string) => {
16
+ if (ref === unresolved) {
17
+ locations.push(location)
18
+ }
19
+ }
20
+
21
+ if (thing instanceof Concept) {
22
+ check(thing.extends, `<Concept>${qualifiedNameOf(thing)}#extends`)
23
+ }
24
+ if (thing instanceof Containment) {
25
+ check(thing.type, `<Containment>${qualifiedNameOf(thing)}#type`)
26
+ }
27
+ if (thing instanceof Property) {
28
+ check(thing.type, `<Property>${qualifiedNameOf(thing)}#type`)
29
+ }
30
+ if (thing instanceof Reference) {
31
+ check(thing.type, `<Reference>${qualifiedNameOf(thing)}#type`)
32
+ }
33
+
34
+ return locations
35
+ }
36
+ )
37
+ // TODO (#8) make this generic, parametrized by a {@link Metamodel}
38
+
@@ -0,0 +1,13 @@
1
+ import { LionWebJsonChunk } from "@lionweb/json"
2
+ import { nodeSerializer } from "../serializer.js"
3
+ import { lioncoreReader } from "./facade.js"
4
+ import { Language } from "./types.js"
5
+
6
+
7
+ /**
8
+ * Serializes languages (i.e., instances of the LionCore metametamodel, using {@link M3Concept these type definitions})
9
+ * into the LionWeb serialization JSON format.
10
+ */
11
+ export const serializeLanguages = (...languages: Language[]): LionWebJsonChunk =>
12
+ nodeSerializer(lioncoreReader)(languages)
13
+
@@ -0,0 +1,119 @@
1
+ import { LionWebJsonMetaPointer, LionWebKey } from "@lionweb/json"
2
+ import { lazyMapGet } from "@lionweb/ts-utils"
3
+ import { allFeaturesOf } from "./functions.js"
4
+ import { Classifier, Feature, Language, LanguageEntity } from "./types.js"
5
+
6
+
7
+ /**
8
+ * Interface for objects that can look up within languages, based on given {@link LionWebJsonMetaPointer meta pointers}.
9
+ * This is meant to be able to properly encapsulate performance optimizations, also outside of the context
10
+ * of deserialization.
11
+ */
12
+ interface SymbolTable {
13
+
14
+ /**
15
+ * Looks up the {@link Language}, as pointed to by the given language key and version.
16
+ */
17
+ languageMatching(key: LionWebKey, version: string): Language | undefined
18
+
19
+ /**
20
+ * Looks up the {@link LanguageEntity}, as pointed to by the given {@link LionWebJsonMetaPointer},
21
+ * or {@code undefined} if it couldn't be found.
22
+ */
23
+ entityMatching(entityMetaPointer: LionWebJsonMetaPointer): LanguageEntity | undefined
24
+
25
+ /**
26
+ * Looks up the {@link Feature}, as pointed to by the {@link LionWebJsonMetaPointer} given second,
27
+ * as a feature of the {@link Classifier}, as pointed to by the {@link LionWebJsonMetaPointer} given first,
28
+ * or {@code undefined} it it couldn't be found.
29
+ * <em>Note</em> that the {@code language} and {@code version} values of both {@link LionWebJsonMetaPointer}-typed arguments should coincide,
30
+ * although this is typically not checked!
31
+ */
32
+ featureMatching(entityMetaPointer: LionWebJsonMetaPointer, featureMetaPointer: LionWebJsonMetaPointer): Feature | undefined
33
+
34
+ }
35
+
36
+
37
+ type EntityInfo = {
38
+ entity: LanguageEntity
39
+ allFeatures: Feature[] // === [] if entity is not a Classifier
40
+ featureKey2feature: { [featureKey: LionWebKey]: Feature } // populated through memoisation
41
+ }
42
+
43
+ class MemoisingSymbolTable implements SymbolTable {
44
+
45
+ private readonly languages: Language[]
46
+
47
+ constructor(languages: Language[]) {
48
+ this.languages = languages
49
+ }
50
+
51
+ private readonly languageKey2version2language: { [languageKey: LionWebKey]: { [version: string]: Language } } = {}
52
+
53
+ languageMatching = (languageKey: LionWebKey, version: string): Language | undefined =>
54
+ lazyMapGet(
55
+ lazyMapGet(this.languageKey2version2language, languageKey, () => ({})),
56
+ version,
57
+ () => this.languages.find((language) =>
58
+ language.key === languageKey
59
+ && language.version === version
60
+ )
61
+ )
62
+
63
+
64
+ private readonly languageKey2version2entityKey2entityInfo: { [languageKey: LionWebKey]: { [version: string]: { [entityKey: LionWebKey]: (EntityInfo | undefined) } } } = {}
65
+
66
+ private entityInfoMatching = (entityMetaPointer: LionWebJsonMetaPointer): undefined | EntityInfo =>
67
+ lazyMapGet(
68
+ lazyMapGet(
69
+ lazyMapGet(this.languageKey2version2entityKey2entityInfo, entityMetaPointer.language, () => ({})),
70
+ entityMetaPointer.version,
71
+ () => ({})
72
+ ),
73
+ entityMetaPointer.key,
74
+ () => {
75
+ const entity = this.languageMatching(entityMetaPointer.language, entityMetaPointer.version)
76
+ ?.entities
77
+ .find((entity) => entity.key === entityMetaPointer.key)
78
+ return entity === undefined
79
+ ? undefined
80
+ : {
81
+ entity,
82
+ allFeatures: entity instanceof Classifier ? allFeaturesOf(entity) : [], featureKey2feature: {}
83
+ }
84
+ }
85
+ )
86
+
87
+ entityMatching = (entityMetaPointer: LionWebJsonMetaPointer): LanguageEntity | undefined =>
88
+ this.entityInfoMatching(entityMetaPointer)?.entity
89
+
90
+ /**
91
+ * Looks up the {@link LanguageEntity}, as pointed to by the given {@link LionWebJsonMetaPointer},
92
+ * and @returns all its {@link Feature features} or an empty array if it couldn't be found.
93
+ */
94
+ allFeaturesOfEntityMatching = (entityMetaPointer: LionWebJsonMetaPointer): Feature[] =>
95
+ this.entityInfoMatching(entityMetaPointer)?.allFeatures ?? []
96
+
97
+ featureMatching(classifierMetaPointer: LionWebJsonMetaPointer, featureMetaPointer: LionWebJsonMetaPointer): Feature | undefined {
98
+ const entityInfo = this.entityInfoMatching(classifierMetaPointer)
99
+ if (entityInfo === undefined || !(entityInfo.entity instanceof Classifier)) {
100
+ return undefined
101
+ }
102
+ return lazyMapGet(
103
+ entityInfo.featureKey2feature,
104
+ featureMetaPointer.key,
105
+ () => entityInfo.allFeatures.find((feature) => feature.key === featureMetaPointer.key)
106
+ )
107
+ }
108
+
109
+ }
110
+
111
+
112
+ export type {
113
+ SymbolTable
114
+ }
115
+
116
+ export {
117
+ MemoisingSymbolTable
118
+ }
119
+
@@ -0,0 +1,325 @@
1
+ /**
2
+ * TypeScript type definitions for the `LionCore` M3 (=meta-meta) model.
3
+ * A LionWeb language (at the M2 meta level) can be represented as an instance of the {@link Language} type.
4
+ */
5
+
6
+ import { LionWebId, LionWebJsonMetaPointer, LionWebKey } from "@lionweb/json"
7
+ import { ResolveInfoDeducer } from "../reading.js"
8
+ import { MultiRef, SingleRef, unresolved } from "../references.js"
9
+ import { Node } from "../types.js"
10
+
11
+
12
+ /**
13
+ * The key of the LionCore language containing the built-ins.
14
+ * (It's defined here because of instantiation order.)
15
+ */
16
+ const lioncoreBuiltinsKey = "LionCore-builtins"
17
+
18
+
19
+ // Types appear roughly in the order of top-to-down+left-to-right in the diagram at:
20
+ // https://lionweb-io.github.io/specification/metametamodel/metametamodel.html#_overview
21
+
22
+
23
+ interface INamed {
24
+ name: string
25
+ }
26
+
27
+ const isINamed = (node: object): node is INamed =>
28
+ "name" in node && typeof node.name === "string"
29
+
30
+ const simpleNameDeducer: ResolveInfoDeducer<Node> =
31
+ (node: Node) => isINamed(node) ? node.name : undefined
32
+
33
+
34
+ interface IKeyed extends INamed {
35
+ key: LionWebId
36
+ }
37
+
38
+
39
+ /**
40
+ * An interface with one method to return a meta type,
41
+ * independent of the class's name obtained through `<node>.constructor.name`,
42
+ * which may be brittle when using bundlers.
43
+ */
44
+ interface IMetaTyped {
45
+ metaType(): string
46
+ }
47
+
48
+ /**
49
+ * Abstract base class for nodes in an LionCore instance,
50
+ * providing an ID, a key, and the containment hierarchy.
51
+ */
52
+ abstract class M3Node implements IKeyed, IMetaTyped {
53
+ metaType(): string {
54
+ throw new Error("#metaType() not implemented")
55
+ }
56
+ parent?: M3Node
57
+ /*
58
+ * Note: every parent in an M2 (i.e., a Language, Concept, Interface, Enumeration) implements IKeyed.
59
+ * Because that's just an interface and is implemented by {@link M3Node},
60
+ * we can type parent as M3Node?.
61
+ */
62
+ readonly id: LionWebId
63
+ name: string
64
+ key: LionWebId
65
+ protected constructor(id: LionWebId, name: string, key: LionWebId, parent?: M3Node) {
66
+ this.id = id
67
+ this.name = name
68
+ this.key = key
69
+ this.parent = parent
70
+ }
71
+ havingKey(key: LionWebId) {
72
+ this.key = key
73
+ return this
74
+ }
75
+ annotations: Node[] = [] // (containment)
76
+ }
77
+
78
+ abstract class Feature extends M3Node {
79
+ optional /*: boolean */ = false
80
+ // TODO look at order of constructors' arguments!
81
+ constructor(classifier: Classifier, name: string, key: LionWebKey, id: LionWebId) {
82
+ super(id, name, key, classifier)
83
+ }
84
+ isOptional() {
85
+ this.optional = true
86
+ return this
87
+ }
88
+ get classifier(): Classifier {
89
+ return this.parent! as Classifier
90
+ }
91
+ }
92
+
93
+ class Property extends Feature {
94
+ metaType(): string {
95
+ return "Property"
96
+ }
97
+ type: SingleRef<DataType> = unresolved // (reference)
98
+ ofType(type: DataType): Property {
99
+ this.type = type
100
+ return this
101
+ }
102
+ }
103
+
104
+ abstract class Link extends Feature {
105
+ multiple /*: boolean */ = false
106
+ type: SingleRef<Classifier> = unresolved // (reference)
107
+ isMultiple() {
108
+ this.multiple = true
109
+ return this
110
+ }
111
+ ofType(type: Classifier) {
112
+ this.type = type
113
+ return this
114
+ }
115
+ }
116
+
117
+ class Containment extends Link {
118
+ metaType(): string {
119
+ return "Containment"
120
+ }
121
+ }
122
+
123
+ class Reference extends Link {
124
+ metaType(): string {
125
+ return "Reference"
126
+ }
127
+ }
128
+
129
+ abstract class LanguageEntity extends M3Node {
130
+ constructor(language: Language, name: string, key: LionWebId, id: LionWebId) {
131
+ super(id, name, key, language)
132
+ }
133
+ get language(): Language {
134
+ return this.parent! as Language
135
+ }
136
+ }
137
+
138
+ abstract class Classifier extends LanguageEntity {
139
+ features: Feature[] = [] // (containment)
140
+ havingFeatures(...features: Feature[]) {
141
+ this.features.push(...features.filter((feature) => this.features.indexOf(feature) < 0))
142
+ return this
143
+ }
144
+ metaPointer(): LionWebJsonMetaPointer {
145
+ const {language} = this
146
+ return {
147
+ language: language.key,
148
+ version: language.version,
149
+ key: this.key
150
+ }
151
+ }
152
+ }
153
+
154
+ class Concept extends Classifier {
155
+ metaType(): string {
156
+ return "Concept"
157
+ }
158
+ abstract: boolean
159
+ partition: boolean
160
+ extends?: SingleRef<Concept> // (reference)
161
+ implements: MultiRef<Interface> = [] // (reference)
162
+ constructor(language: Language, name: string, key: LionWebKey, id: LionWebId, abstract: boolean, extends_?: SingleRef<Concept>) {
163
+ super(language, name, key, id)
164
+ this.abstract = abstract
165
+ this.extends = extends_
166
+ this.partition = false
167
+ }
168
+ implementing(...interfaces: Interface[]): Concept {
169
+ // TODO check actual types of interfaces, or use type shapes/interfaces
170
+ this.implements.push(...interfaces)
171
+ return this
172
+ }
173
+ isPartition(): Concept {
174
+ this.partition = true
175
+ return this
176
+ }
177
+ }
178
+
179
+ class Annotation extends Classifier {
180
+ metaType(): string {
181
+ return "Annotation"
182
+ }
183
+ extends?: SingleRef<Annotation> // (reference)
184
+ implements: MultiRef<Interface> = [] // (reference)
185
+ annotates: SingleRef<Classifier> = unresolved // (reference)
186
+ constructor(language: Language, name: string, key: LionWebKey, id: LionWebId, extends_?: SingleRef<Annotation>) {
187
+ super(language, name, key, id)
188
+ this.extends = extends_
189
+ }
190
+ implementing(...interfaces: Interface[]): Annotation {
191
+ // TODO check actual types of interfaces, or use type shapes/interfaces
192
+ this.implements.push(...interfaces)
193
+ return this
194
+ }
195
+ annotating(classifier: Classifier): Annotation {
196
+ this.annotates = classifier
197
+ return this
198
+ }
199
+ }
200
+
201
+ class Interface extends Classifier {
202
+ metaType(): string {
203
+ return "Interface"
204
+ }
205
+ extends: MultiRef<Interface> = [] // (reference)
206
+ extending(...interfaces: Interface[]): Interface {
207
+ // TODO check actual types of interfaces, or use type shapes/interfaces
208
+ this.extends.push(...interfaces)
209
+ return this
210
+ }
211
+ }
212
+
213
+ abstract class DataType extends LanguageEntity {}
214
+
215
+ /**
216
+ * Misspelled alias of {@link DataType}, kept for backward compatibility, and to be deprecated and removed later.
217
+ */
218
+ abstract class Datatype extends DataType {}
219
+
220
+ class PrimitiveType extends DataType {
221
+ metaType(): string {
222
+ return "PrimitiveType"
223
+ }
224
+ }
225
+
226
+ class Enumeration extends DataType {
227
+ metaType(): string {
228
+ return "Enumeration"
229
+ }
230
+ literals: EnumerationLiteral[] = [] // (containment)
231
+ havingLiterals(...literals: EnumerationLiteral[]) {
232
+ this.literals.push(...literals.filter((literal) => this.literals.indexOf(literal) < 0))
233
+ return this
234
+ }
235
+ }
236
+
237
+ class EnumerationLiteral extends M3Node {
238
+ metaType(): string {
239
+ return "EnumerationLiteral"
240
+ }
241
+ constructor(enumeration: Enumeration, name: string, key: LionWebKey, id: LionWebId) {
242
+ super(id, name, key, enumeration)
243
+ }
244
+ get enumeration(): Enumeration {
245
+ return this.parent! as Enumeration
246
+ }
247
+ }
248
+
249
+ class Language extends M3Node {
250
+ metaType(): string {
251
+ return "Language"
252
+ }
253
+ version: string
254
+ entities: LanguageEntity[] = [] // (containment)
255
+ dependsOn: MultiRef<Language> = [] // special (!) reference
256
+ // (!) special because deserializer needs to be aware of where to get the instance from
257
+ constructor(name: string, version: string, id: LionWebId, key: LionWebKey) {
258
+ super(id, name, key)
259
+ this.version = version
260
+ }
261
+ havingEntities(...entities: LanguageEntity[]): Language {
262
+ this.entities.push(...entities.filter((entity) => this.entities.indexOf(entity) < 0))
263
+ return this
264
+ }
265
+ dependingOn(...languages: Language[]): Language {
266
+ this.dependsOn.push(
267
+ ...languages
268
+ .filter((language) => language.key !== lioncoreBuiltinsKey)
269
+ )
270
+ return this
271
+ }
272
+ equals(that: Language): boolean {
273
+ return this.key === that.key && this.version === that.version
274
+ }
275
+ }
276
+
277
+
278
+ /**
279
+ * Sum type of all LionCore type definitions whose meta-type is a concrete (thus: instantiable) Concept.
280
+ * All the classes in this sum type extend (from) {@link M3Node},
281
+ * so they also implement {@link INamed} and {@link IKeyed}.
282
+ */
283
+ type M3Concept =
284
+ | Annotation
285
+ | Concept
286
+ | Containment
287
+ | Enumeration
288
+ | EnumerationLiteral
289
+ | Interface
290
+ | Language
291
+ | PrimitiveType
292
+ | Property
293
+ | Reference
294
+
295
+
296
+ export {
297
+ Annotation,
298
+ Classifier,
299
+ Concept,
300
+ Containment,
301
+ DataType,
302
+ Datatype,
303
+ Enumeration,
304
+ EnumerationLiteral,
305
+ Feature,
306
+ Interface,
307
+ Language,
308
+ LanguageEntity,
309
+ Link,
310
+ PrimitiveType,
311
+ Property,
312
+ Reference,
313
+ isINamed,
314
+ lioncoreBuiltinsKey,
315
+ simpleNameDeducer
316
+ }
317
+
318
+ export type {
319
+ IKeyed,
320
+ IMetaTyped,
321
+ INamed,
322
+ M3Concept,
323
+ M3Node
324
+ }
325
+
package/src/reading.ts ADDED
@@ -0,0 +1,55 @@
1
+ import { Classifier, Enumeration, EnumerationLiteral, Feature } from "./m3/index.js"
2
+ import { Node } from "./types.js"
3
+
4
+
5
+ /**
6
+ * Type def. for functions that deduce the {@link Classifier classifier} of a given {@link Node node}.
7
+ */
8
+ export type ClassifierDeducer<NT extends Node> = (node: NT) => Classifier
9
+
10
+ /**
11
+ * Type def. for functions that deduce the string value of the `resolveInfo` field of a
12
+ * {@link LionWebJsonReferenceTarget serialized reference target}, or {@code undefined}
13
+ * to indicate that no `resolveInfo` could be derived.
14
+ */
15
+ export type ResolveInfoDeducer<NT extends Node> = (node: NT) => string | undefined
16
+
17
+ /**
18
+ * An interface that's used to parametrize generic serialization of
19
+ * (in-memory) nodes of the given type (parameter).
20
+ * Implementations of these interfaces {w|c}ould be:
21
+ * - specific to LionCore (so to match m3/types.ts)
22
+ * - generic to serialize {@link DynamicNode dynamic nodes}
23
+ */
24
+ export interface Reader<NT extends Node> {
25
+
26
+ /**
27
+ * @return The {@link Concept concept} of the given node
28
+ */
29
+ classifierOf: ClassifierDeducer<NT>
30
+
31
+ /**
32
+ * @return The value of the given {@link Feature feature} on the given node.
33
+ */
34
+ getFeatureValue: (node: NT, feature: Feature) => unknown
35
+ // TODO split to getPropertyValue, &c.?
36
+
37
+ /**
38
+ * @return The {@link EnumerationLiteral} corresponding to
39
+ * the given {@link Enumeration} and the runtime encoding of a literal of it,
40
+ */
41
+ enumerationLiteralFrom: (encoding: unknown, enumeration: Enumeration) => EnumerationLiteral | null
42
+
43
+ /**
44
+ * @return The string value of the `resolveInfo` field of a {@link LionWebJsonReferenceTarget serialized reference target},
45
+ * or {@code undefined} to indicate that no `resolveInfo` could be derived.
46
+ */
47
+ resolveInfoFor?: ResolveInfoDeducer<NT>
48
+
49
+ }
50
+
51
+ /**
52
+ * Alias for {@link Reader}, kept for backward compatibility, and to be deprecated and removed later.
53
+ */
54
+ export interface ExtractionFacade<NT extends Node> extends Reader<NT> {}
55
+
@@ -0,0 +1,31 @@
1
+ import { LionWebId } from "@lionweb/json"
2
+
3
+
4
+ /**
5
+ * The `unresolved` symbol indicates a reference value which hasn't been resolved yet.
6
+ * It differs from an unset (`undefined`) value.
7
+ */
8
+ export const unresolved = null
9
+
10
+ /**
11
+ * A type definition for a reference value that can be unresolved.
12
+ */
13
+ export type SingleRef<T> = typeof unresolved | T
14
+
15
+ /**
16
+ * Checks whether a given (at most) single-valued reference actually refers to something.
17
+ */
18
+ export const isRef = <T>(ref?: SingleRef<T>): ref is T =>
19
+ ref !== undefined && ref !== unresolved
20
+
21
+ /**
22
+ * A type alias for a multi-valued reference, to make it look consistent with {@link SingleRef}.
23
+ */
24
+ export type MultiRef<T> = T[]
25
+
26
+
27
+ /**
28
+ * A type that expresses a value is either an {@link LionWebId} or a value to indicate that resolution to a node previously failed.
29
+ */
30
+ export type IdOrUnresolved = LionWebId | typeof unresolved;
31
+