@oml/language 0.9.0 → 0.11.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.
@@ -1,7 +1,7 @@
1
1
  // Copyright (c) 2026 Modelware. All rights reserved.
2
- import { URI } from 'langium';
2
+ import { DocumentState, URI } from 'langium';
3
3
  import { RequestType } from 'vscode-languageserver-protocol';
4
- import { isAnnotation, isConceptInstance, isDescription, isImport, isOntology, isPropertyValueAssertion, isRelationInstance, isRule, isTypeAssertion, } from './generated/ast.js';
4
+ import { isAnnotation, isConceptInstance, isDescription, isDescriptionBox, isImport, isOntology, isPropertyValueAssertion, isRelationInstance, isRule, isTypeAssertion, isVocabulary, isVocabularyBundle, } from './generated/ast.js';
5
5
  import { getOntologyModelIndex } from './oml-index.js';
6
6
  import { serializeOntology } from './oml-serializer.js';
7
7
  import { collectOntologyMembers, findOntologyMemberByName, getIriForNode, normalizeNamespace, } from './oml-utils.js';
@@ -58,7 +58,12 @@ async function resolveOntologyContext(shared, ontologyIri, cache) {
58
58
  const builder = shared.workspace.DocumentBuilder;
59
59
  const document = langiumDocuments.getDocument(uri)
60
60
  ?? await langiumDocuments.getOrCreateDocument(uri);
61
- await builder.build([document], { validation: true });
61
+ // Only build if not yet Linked. Forcing validation:true when the workspace
62
+ // is already Validated causes a document-state conflict in Langium on Windows.
63
+ const docState = document?.state;
64
+ if (docState === undefined || docState < DocumentState.Linked) {
65
+ await builder.build([document], { validation: false });
66
+ }
62
67
  const ontology = document?.parseResult?.value;
63
68
  if (!ontology || !isOntology(ontology)) {
64
69
  throw new Error(`Resolved document '${modelUri}' is not an ontology.`);
@@ -85,8 +90,7 @@ async function executeOperation(shared, context, operation, contexts) {
85
90
  ownedPropertyValues: [],
86
91
  ownedTypes: []
87
92
  };
88
- statement.$container = context.ontology;
89
- context.ontology.ownedStatements.push(statement);
93
+ pushAstArrayChild(context.ontology, 'ownedStatements', statement);
90
94
  }
91
95
  return new Set([context.ontologyIri]);
92
96
  case 'createRelationInstance':
@@ -102,15 +106,14 @@ async function executeOperation(shared, context, operation, contexts) {
102
106
  sources: [],
103
107
  targets: []
104
108
  };
105
- statement.$container = context.ontology;
106
- context.ontology.ownedStatements.push(statement);
109
+ pushAstArrayChild(context.ontology, 'ownedStatements', statement);
107
110
  }
108
111
  return new Set([context.ontologyIri]);
109
112
  case 'createInstanceRef':
110
113
  ensureDescriptionOntology(context.ontology, operation.kind);
111
- ensureReferenceImport(context.ontology, operation.instanceIri);
114
+ await ensureReferenceImport(shared, context.ontology, operation.instanceIri);
112
115
  if (operation.typeIri) {
113
- ensureReferenceImport(context.ontology, operation.typeIri);
116
+ await ensureReferenceImport(shared, context.ontology, operation.typeIri);
114
117
  }
115
118
  {
116
119
  const ownedTypes = [];
@@ -128,15 +131,17 @@ async function executeOperation(shared, context, operation, contexts) {
128
131
  ownedTypes
129
132
  };
130
133
  statement.__targetIri = normalizeIri(operation.instanceIri);
131
- statement.$container = context.ontology;
132
- context.ontology.ownedStatements.push(statement);
134
+ pushAstArrayChild(context.ontology, 'ownedStatements', statement);
135
+ for (const typeAssertion of ownedTypes) {
136
+ attachAstNode(typeAssertion, statement, 'ownedTypes');
137
+ }
133
138
  }
134
139
  return new Set([context.ontologyIri]);
135
140
  case 'createRelationInstanceRef':
136
141
  ensureDescriptionOntology(context.ontology, operation.kind);
137
- ensureReferenceImport(context.ontology, operation.instanceIri);
142
+ await ensureReferenceImport(shared, context.ontology, operation.instanceIri);
138
143
  if (operation.typeIri) {
139
- ensureReferenceImport(context.ontology, operation.typeIri);
144
+ await ensureReferenceImport(shared, context.ontology, operation.typeIri);
140
145
  }
141
146
  {
142
147
  const ownedTypes = [];
@@ -156,13 +161,20 @@ async function executeOperation(shared, context, operation, contexts) {
156
161
  targets: []
157
162
  };
158
163
  statement.__targetIri = normalizeIri(operation.instanceIri);
159
- statement.$container = context.ontology;
160
- context.ontology.ownedStatements.push(statement);
164
+ pushAstArrayChild(context.ontology, 'ownedStatements', statement);
165
+ for (const typeAssertion of ownedTypes) {
166
+ attachAstNode(typeAssertion, statement, 'ownedTypes');
167
+ }
161
168
  }
162
169
  return new Set([context.ontologyIri]);
163
170
  case 'addAssertion':
164
171
  ensureDescriptionOntology(context.ontology, operation.kind);
165
- return addAssertion(context.ontology, operation.subjectIri, operation.predicateIri, operation.object)
172
+ return await addAssertion(shared, context.ontology, operation.subjectIri, operation.predicateIri, operation.object)
173
+ ? new Set([context.ontologyIri])
174
+ : new Set();
175
+ case 'updateAssertion':
176
+ ensureDescriptionOntology(context.ontology, operation.kind);
177
+ return await updateAssertion(shared, context.ontology, operation.subjectIri, operation.predicateIri, operation.object)
166
178
  ? new Set([context.ontologyIri])
167
179
  : new Set();
168
180
  case 'removeAssertion':
@@ -171,7 +183,11 @@ async function executeOperation(shared, context, operation, contexts) {
171
183
  ? new Set([context.ontologyIri])
172
184
  : new Set();
173
185
  case 'addAnnotation':
174
- return addAnnotation(context.ontology, operation.subjectIri, operation.predicateIri, operation.object)
186
+ return await addAnnotation(shared, context.ontology, operation.subjectIri, operation.predicateIri, operation.object)
187
+ ? new Set([context.ontologyIri])
188
+ : new Set();
189
+ case 'updateAnnotation':
190
+ return await updateAnnotation(shared, context.ontology, operation.subjectIri, operation.predicateIri, operation.object)
175
191
  ? new Set([context.ontologyIri])
176
192
  : new Set();
177
193
  case 'removeAnnotation':
@@ -200,7 +216,10 @@ async function resolveOntologyContextByModelUri(shared, modelUri, cache) {
200
216
  const builder = shared.workspace.DocumentBuilder;
201
217
  const document = langiumDocuments.getDocument(uri)
202
218
  ?? await langiumDocuments.getOrCreateDocument(uri);
203
- await builder.build([document], { validation: true });
219
+ const docState2 = document?.state;
220
+ if (docState2 === undefined || docState2 < DocumentState.Linked) {
221
+ await builder.build([document], { validation: false });
222
+ }
204
223
  const ontology = document?.parseResult?.value;
205
224
  if (!ontology || !isOntology(ontology)) {
206
225
  throw new Error(`Resolved document '${modelUri}' is not an ontology.`);
@@ -225,7 +244,7 @@ function ensureUniqueLocalName(ontology, memberName) {
225
244
  throw new Error(`A member named '${memberName}' already exists in the ontology.`);
226
245
  }
227
246
  }
228
- function addAssertion(ontology, subjectIri, predicateIri, objectValue) {
247
+ async function addAssertion(shared, ontology, subjectIri, predicateIri, objectValue) {
229
248
  const normalizedPredicate = normalizeIri(predicateIri);
230
249
  const subject = findNamedInstanceByIri(ontology, subjectIri);
231
250
  if (!subject) {
@@ -236,9 +255,9 @@ function addAssertion(ontology, subjectIri, predicateIri, objectValue) {
236
255
  if ((subject.ownedTypes ?? []).some((entry) => matchesPredicateRef(ontology, entry?.type, normalizedTypeIri))) {
237
256
  return false;
238
257
  }
239
- ensureReferenceImport(ontology, normalizedTypeIri);
258
+ await ensureReferenceImport(shared, ontology, normalizedTypeIri);
240
259
  subject.ownedTypes ?? (subject.ownedTypes = []);
241
- subject.ownedTypes.push({
260
+ pushAstArrayChild(subject, 'ownedTypes', {
242
261
  $type: 'TypeAssertion',
243
262
  type: asRef(ontology, normalizedTypeIri)
244
263
  });
@@ -249,7 +268,7 @@ function addAssertion(ontology, subjectIri, predicateIri, objectValue) {
249
268
  throw new Error(`Predicate '${predicateIri}' applies only to relation instances.`);
250
269
  }
251
270
  const sourceIri = normalizeIri(asRequiredIri(objectValue, 'source assertion object'));
252
- ensureReferenceImport(ontology, sourceIri);
271
+ await ensureReferenceImport(shared, ontology, sourceIri);
253
272
  subject.sources ?? (subject.sources = []);
254
273
  subject.sources.push(asRef(ontology, sourceIri));
255
274
  return true;
@@ -259,7 +278,7 @@ function addAssertion(ontology, subjectIri, predicateIri, objectValue) {
259
278
  throw new Error(`Predicate '${predicateIri}' applies only to relation instances.`);
260
279
  }
261
280
  const targetIri = normalizeIri(asRequiredIri(objectValue, 'target assertion object'));
262
- ensureReferenceImport(ontology, targetIri);
281
+ await ensureReferenceImport(shared, ontology, targetIri);
263
282
  subject.targets ?? (subject.targets = []);
264
283
  subject.targets.push(asRef(ontology, targetIri));
265
284
  return true;
@@ -267,6 +286,7 @@ function addAssertion(ontology, subjectIri, predicateIri, objectValue) {
267
286
  subject.ownedPropertyValues ?? (subject.ownedPropertyValues = []);
268
287
  let propertyAssertion = subject.ownedPropertyValues.find((assertion) => matchesPredicateRef(ontology, assertion?.property, normalizedPredicate));
269
288
  if (!propertyAssertion) {
289
+ await ensureReferenceImport(shared, ontology, normalizedPredicate);
270
290
  propertyAssertion = {
271
291
  $type: 'PropertyValueAssertion',
272
292
  property: asRef(ontology, normalizedPredicate),
@@ -274,7 +294,13 @@ function addAssertion(ontology, subjectIri, predicateIri, objectValue) {
274
294
  referencedValues: [],
275
295
  containedValues: []
276
296
  };
277
- subject.ownedPropertyValues.push(propertyAssertion);
297
+ pushAstArrayChild(subject, 'ownedPropertyValues', propertyAssertion);
298
+ }
299
+ if (isIriLike(objectValue)) {
300
+ await ensureReferenceImport(shared, ontology, normalizeIri(asRequiredIri(objectValue, 'assertion object')));
301
+ }
302
+ else {
303
+ await ensureTypedLiteralDatatypeImport(shared, ontology, objectValue);
278
304
  }
279
305
  appendAssertionValue(ontology, propertyAssertion, objectValue);
280
306
  return true;
@@ -367,20 +393,56 @@ function removeAssertion(ontology, subjectIri, predicateIri, objectValue) {
367
393
  subject.ownedPropertyValues = remaining;
368
394
  return changed;
369
395
  }
370
- function addAnnotation(ontology, subjectIri, predicateIri, objectValue) {
396
+ async function updateAssertion(shared, ontology, subjectIri, predicateIri, objectValue) {
397
+ const normalizedPredicate = normalizeIri(predicateIri);
398
+ const subject = findNamedInstanceByIri(ontology, subjectIri);
399
+ if (!subject) {
400
+ throw new Error(`Subject '${subjectIri}' was not found in the ontology.`);
401
+ }
402
+ if (normalizedPredicate === RDF_TYPE_IRI || isSourcePredicate(normalizedPredicate) || isTargetPredicate(normalizedPredicate)) {
403
+ const removed = removeAssertion(ontology, subjectIri, predicateIri, undefined);
404
+ const added = await addAssertion(shared, ontology, subjectIri, predicateIri, objectValue);
405
+ return removed || added;
406
+ }
407
+ subject.ownedPropertyValues ?? (subject.ownedPropertyValues = []);
408
+ let propertyAssertion = subject.ownedPropertyValues.find((assertion) => matchesPredicateRef(ontology, assertion?.property, normalizedPredicate));
409
+ if (!propertyAssertion) {
410
+ return addAssertion(shared, ontology, subjectIri, predicateIri, objectValue);
411
+ }
412
+ if (isIriLike(objectValue)) {
413
+ await ensureReferenceImport(shared, ontology, normalizeIri(asRequiredIri(objectValue, 'assertion object')));
414
+ }
415
+ else {
416
+ await ensureTypedLiteralDatatypeImport(shared, ontology, objectValue);
417
+ }
418
+ propertyAssertion.literalValues = [];
419
+ propertyAssertion.referencedValues = [];
420
+ propertyAssertion.containedValues = [];
421
+ appendAssertionValue(ontology, propertyAssertion, objectValue);
422
+ return true;
423
+ }
424
+ async function addAnnotation(shared, ontology, subjectIri, predicateIri, objectValue) {
371
425
  const subject = findAnnotationSubjectByIri(ontology, subjectIri);
372
426
  if (!subject) {
373
427
  throw new Error(`Annotation subject '${subjectIri}' was not found in the ontology.`);
374
428
  }
429
+ const normalizedPredicate = normalizeIri(predicateIri);
430
+ await ensureReferenceImport(shared, ontology, normalizedPredicate);
375
431
  subject.ownedAnnotations ?? (subject.ownedAnnotations = []);
376
432
  const annotation = {
377
433
  $type: 'Annotation',
378
- property: asRef(ontology, predicateIri),
434
+ property: asRef(ontology, normalizedPredicate),
379
435
  literalValues: [],
380
436
  referencedValues: []
381
437
  };
438
+ if (isIriLike(objectValue)) {
439
+ await ensureReferenceImport(shared, ontology, normalizeIri(asRequiredIri(objectValue, 'annotation object')));
440
+ }
441
+ else {
442
+ await ensureTypedLiteralDatatypeImport(shared, ontology, objectValue);
443
+ }
382
444
  appendAnnotationValue(ontology, annotation, objectValue);
383
- subject.ownedAnnotations.push(annotation);
445
+ pushAstArrayChild(subject, 'ownedAnnotations', annotation);
384
446
  return true;
385
447
  }
386
448
  function removeAnnotation(ontology, subjectIri, predicateIri, objectValue) {
@@ -420,6 +482,28 @@ function removeAnnotation(ontology, subjectIri, predicateIri, objectValue) {
420
482
  subject.ownedAnnotations = kept;
421
483
  return changed;
422
484
  }
485
+ async function updateAnnotation(shared, ontology, subjectIri, predicateIri, objectValue) {
486
+ const subject = findAnnotationSubjectByIri(ontology, subjectIri);
487
+ if (!subject) {
488
+ throw new Error(`Annotation subject '${subjectIri}' was not found in the ontology.`);
489
+ }
490
+ const normalizedPredicate = normalizeIri(predicateIri);
491
+ subject.ownedAnnotations ?? (subject.ownedAnnotations = []);
492
+ const annotation = subject.ownedAnnotations.find((entry) => matchesPredicateRef(ontology, entry?.property, normalizedPredicate));
493
+ if (!annotation) {
494
+ return addAnnotation(shared, ontology, subjectIri, predicateIri, objectValue);
495
+ }
496
+ if (isIriLike(objectValue)) {
497
+ await ensureReferenceImport(shared, ontology, normalizeIri(asRequiredIri(objectValue, 'annotation object')));
498
+ }
499
+ else {
500
+ await ensureTypedLiteralDatatypeImport(shared, ontology, objectValue);
501
+ }
502
+ annotation.literalValues = [];
503
+ annotation.referencedValues = [];
504
+ appendAnnotationValue(ontology, annotation, objectValue);
505
+ return true;
506
+ }
423
507
  function deleteMemberRef(ontology, memberIri, typeIri) {
424
508
  if (!Array.isArray(ontology.ownedStatements)) {
425
509
  return false;
@@ -718,9 +802,7 @@ function matchesPredicateRef(ontology, ref, iri) {
718
802
  return false;
719
803
  }
720
804
  const normalizedWanted = normalizeIri(iri);
721
- const refText = typeof ref === 'string'
722
- ? ref
723
- : (typeof ref.$refText === 'string' ? ref.$refText : undefined);
805
+ const refText = getRefText(ref);
724
806
  if (refText) {
725
807
  const normalizedRefText = normalizeIri(expandRefTextToIri(ontology, refText) ?? refText);
726
808
  if (isSameIriTarget(normalizedRefText, normalizedWanted)) {
@@ -734,13 +816,12 @@ function matchesPredicateRef(ontology, ref, iri) {
734
816
  function appendAssertionValue(ontology, assertion, objectValue) {
735
817
  if (isIriLike(objectValue)) {
736
818
  const normalizedObjectIri = normalizeIri(asRequiredIri(objectValue, 'assertion object'));
737
- ensureReferenceImport(ontology, normalizedObjectIri);
738
819
  assertion.referencedValues ?? (assertion.referencedValues = []);
739
820
  assertion.referencedValues.push(asRef(ontology, normalizedObjectIri));
740
821
  return;
741
822
  }
742
823
  assertion.literalValues ?? (assertion.literalValues = []);
743
- assertion.literalValues.push(asLiteral(objectValue));
824
+ pushAstArrayChild(assertion, 'literalValues', asLiteral(ontology, objectValue));
744
825
  }
745
826
  function removeAssertionValue(ontology, assertion, objectValue) {
746
827
  if (isIriLike(objectValue)) {
@@ -748,19 +829,18 @@ function removeAssertionValue(ontology, assertion, objectValue) {
748
829
  assertion.referencedValues = (assertion.referencedValues ?? []).filter((ref) => !matchesPredicateRef(ontology, ref, normalizedIri));
749
830
  return;
750
831
  }
751
- const normalizedLiteral = normalizeLiteralValue(asLiteral(objectValue));
832
+ const normalizedLiteral = normalizeLiteralValue(asLiteral(ontology, objectValue));
752
833
  assertion.literalValues = (assertion.literalValues ?? []).filter((literal) => normalizeLiteralValue(literal) !== normalizedLiteral);
753
834
  }
754
835
  function appendAnnotationValue(ontology, annotation, objectValue) {
755
836
  if (isIriLike(objectValue)) {
756
837
  const normalizedObjectIri = normalizeIri(asRequiredIri(objectValue, 'annotation object'));
757
- ensureReferenceImport(ontology, normalizedObjectIri);
758
838
  annotation.referencedValues ?? (annotation.referencedValues = []);
759
839
  annotation.referencedValues.push(asRef(ontology, normalizedObjectIri));
760
840
  return;
761
841
  }
762
842
  annotation.literalValues ?? (annotation.literalValues = []);
763
- annotation.literalValues.push(asLiteral(objectValue));
843
+ pushAstArrayChild(annotation, 'literalValues', asLiteral(ontology, objectValue));
764
844
  }
765
845
  function removeAnnotationValue(ontology, annotation, objectValue) {
766
846
  if (isIriLike(objectValue)) {
@@ -768,7 +848,7 @@ function removeAnnotationValue(ontology, annotation, objectValue) {
768
848
  annotation.referencedValues = (annotation.referencedValues ?? []).filter((ref) => !matchesPredicateRef(ontology, ref, normalizedIri));
769
849
  return;
770
850
  }
771
- const normalizedLiteral = normalizeLiteralValue(asLiteral(objectValue));
851
+ const normalizedLiteral = normalizeLiteralValue(asLiteral(ontology, objectValue));
772
852
  annotation.literalValues = (annotation.literalValues ?? []).filter((literal) => normalizeLiteralValue(literal) !== normalizedLiteral);
773
853
  }
774
854
  function normalizeLiteralValue(literal) {
@@ -893,7 +973,7 @@ function expandLocalRefText(rawNamespace, localName) {
893
973
  }
894
974
  return `${namespace}#${local}`;
895
975
  }
896
- function ensureReferenceImport(ontology, iri) {
976
+ async function ensureReferenceImport(shared, ontology, iri) {
897
977
  const target = parseIriParts(iri);
898
978
  if (!target) {
899
979
  return;
@@ -923,17 +1003,53 @@ function ensureReferenceImport(ontology, iri) {
923
1003
  }
924
1004
  const prefix = pickImportPrefix(target.namespace, usedPrefixes);
925
1005
  const importedRef = `<${target.namespace}${target.separator}>`;
1006
+ const importKind = await resolveImportKind(shared, ontology, target.namespace);
926
1007
  const importStatement = {
927
1008
  $type: 'Import',
928
- kind: 'extends',
1009
+ kind: importKind,
929
1010
  prefix,
930
1011
  imported: { $refText: importedRef }
931
1012
  };
932
- importStatement.$container = ontology;
933
- if (!Array.isArray(ontology.ownedImports)) {
934
- ontology.ownedImports = [];
1013
+ pushAstArrayChild(ontology, 'ownedImports', importStatement);
1014
+ }
1015
+ async function resolveImportKind(shared, importing, importedNamespace) {
1016
+ const imported = await findOntologyByNamespace(shared, importedNamespace);
1017
+ if (imported) {
1018
+ if (importing.$type === imported.$type) {
1019
+ return 'extends';
1020
+ }
1021
+ if (isVocabulary(importing) && isDescription(imported)) {
1022
+ return 'uses';
1023
+ }
1024
+ if (isDescriptionBox(importing) && isVocabulary(imported)) {
1025
+ return 'uses';
1026
+ }
1027
+ if (isVocabularyBundle(importing) && isVocabulary(imported)) {
1028
+ return 'includes';
1029
+ }
1030
+ }
1031
+ if (isVocabularyBundle(importing)) {
1032
+ return 'includes';
1033
+ }
1034
+ if (isDescriptionBox(importing)) {
1035
+ return 'uses';
935
1036
  }
936
- ontology.ownedImports.push(importStatement);
1037
+ return 'extends';
1038
+ }
1039
+ async function findOntologyByNamespace(shared, namespace) {
1040
+ const index = getOntologyModelIndex(shared);
1041
+ const modelUri = index.resolveModelUri(normalizeNamespace(namespace));
1042
+ if (!modelUri) {
1043
+ return undefined;
1044
+ }
1045
+ const uri = URI.parse(modelUri);
1046
+ const langiumDocuments = shared.workspace.LangiumDocuments;
1047
+ const builder = shared.workspace.DocumentBuilder;
1048
+ const document = langiumDocuments.getDocument(uri)
1049
+ ?? await langiumDocuments.getOrCreateDocument(uri);
1050
+ await builder.build([document], { validation: false });
1051
+ const ontology = document?.parseResult?.value;
1052
+ return ontology && isOntology(ontology) ? ontology : undefined;
937
1053
  }
938
1054
  function parseIriParts(iri) {
939
1055
  const normalized = normalizeIri(iri);
@@ -1070,7 +1186,17 @@ function pickImportPrefix(namespace, usedPrefixes) {
1070
1186
  }
1071
1187
  return `${candidateBase}${suffix}`;
1072
1188
  }
1073
- function asLiteral(value) {
1189
+ function asLiteral(ontology, value) {
1190
+ if (isTypedQuotedLiteralTransport(value)) {
1191
+ const literalValue = String(value.value ?? '');
1192
+ const datatypeIri = typeof value.datatypeIri === 'string' ? value.datatypeIri.trim() : '';
1193
+ const datatypeRefText = typeof value.datatypeRefText === 'string' ? value.datatypeRefText.trim() : '';
1194
+ return datatypeIri
1195
+ ? { $type: 'QuotedLiteral', value: literalValue, type: { $refText: toRefText(ontology, normalizeIri(datatypeIri)) } }
1196
+ : datatypeRefText
1197
+ ? { $type: 'QuotedLiteral', value: literalValue, type: { $refText: datatypeRefText } }
1198
+ : { $type: 'QuotedLiteral', value: literalValue };
1199
+ }
1074
1200
  if (typeof value === 'boolean') {
1075
1201
  return { $type: 'BooleanLiteral', value };
1076
1202
  }
@@ -1082,6 +1208,38 @@ function asLiteral(value) {
1082
1208
  }
1083
1209
  return { $type: 'QuotedLiteral', value: String(value ?? '') };
1084
1210
  }
1211
+ async function ensureTypedLiteralDatatypeImport(shared, ontology, value) {
1212
+ if (!isTypedQuotedLiteralTransport(value)) {
1213
+ return;
1214
+ }
1215
+ const datatypeIri = typeof value.datatypeIri === 'string' ? normalizeIri(value.datatypeIri) : '';
1216
+ if (!datatypeIri) {
1217
+ return;
1218
+ }
1219
+ await ensureReferenceImport(shared, ontology, datatypeIri);
1220
+ }
1221
+ function isTypedQuotedLiteralTransport(value) {
1222
+ if (!value || typeof value !== 'object' || Array.isArray(value)) {
1223
+ return false;
1224
+ }
1225
+ const record = value;
1226
+ if (record.$type === 'QuotedLiteral') {
1227
+ return true;
1228
+ }
1229
+ return (typeof record.datatypeIri === 'string' || typeof record.datatypeRefText === 'string') && 'value' in record;
1230
+ }
1231
+ function attachAstNode(node, parent, containerProperty) {
1232
+ node.$container = parent;
1233
+ node.$containerProperty = containerProperty;
1234
+ return node;
1235
+ }
1236
+ function pushAstArrayChild(parent, property, node) {
1237
+ if (!Array.isArray(parent[property])) {
1238
+ parent[property] = [];
1239
+ }
1240
+ attachAstNode(node, parent, property);
1241
+ parent[property].push(node);
1242
+ }
1085
1243
  function asRequiredIri(value, context) {
1086
1244
  if (!isIriLike(value)) {
1087
1245
  throw new Error(`Expected IRI for ${context}.`);