@semiont/graph 0.5.26 → 0.5.28

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 (55) hide show
  1. package/dist/{chunk-GPJBZ6EG.js → chunk-2FPUYYXX.js} +9 -1
  2. package/dist/chunk-2FPUYYXX.js.map +1 -0
  3. package/dist/{chunk-Y62BMZ25.js → chunk-52FQCX5M.js} +18 -6
  4. package/dist/chunk-52FQCX5M.js.map +1 -0
  5. package/dist/{chunk-RKAR27K2.js → chunk-MO34K2LQ.js} +119 -28
  6. package/dist/chunk-MO34K2LQ.js.map +1 -0
  7. package/dist/{chunk-JWG64MVA.js → chunk-RUKYB5L4.js} +6 -6
  8. package/dist/{chunk-JWG64MVA.js.map → chunk-RUKYB5L4.js.map} +1 -1
  9. package/dist/{chunk-YYVVWLB2.js → chunk-TKWHSSPF.js} +35 -16
  10. package/dist/chunk-TKWHSSPF.js.map +1 -0
  11. package/dist/{chunk-RRZDPP7Z.js → chunk-X77CPJUJ.js} +2 -2
  12. package/dist/{chunk-UKT6IXAM.js → chunk-XTHXGGIJ.js} +3 -3
  13. package/dist/{chunk-RBRHTAJN.js → chunk-ZPM4D2XD.js} +14 -5
  14. package/dist/chunk-ZPM4D2XD.js.map +1 -0
  15. package/dist/{dist-es-BGEPUOPB.js → dist-es-AET2QNVA.js} +21 -21
  16. package/dist/dist-es-AET2QNVA.js.map +1 -0
  17. package/dist/{dist-es-TLOL2VHU.js → dist-es-BSJRQ6XP.js} +7 -7
  18. package/dist/{dist-es-BUTLC2YS.js → dist-es-C2VXNLLU.js} +13 -13
  19. package/dist/{dist-es-M72B762W.js → dist-es-FTEZAK7G.js} +5 -5
  20. package/dist/{dist-es-NGG7JHEH.js → dist-es-FV5JDCUX.js} +4 -4
  21. package/dist/{dist-es-WLYFLMD3.js → dist-es-IS4IC3TZ.js} +5 -5
  22. package/dist/{dist-es-ILOZ33QI.js → dist-es-ISXX5KU4.js} +5 -5
  23. package/dist/{dist-es-WS6NDSQ5.js → dist-es-RR4OU64S.js} +5 -5
  24. package/dist/{dist-es-LN4LZWKV.js → dist-es-V7467ELV.js} +3 -3
  25. package/dist/{event-streams-2HBIXE6X.js → event-streams-UU2VASBU.js} +36 -27
  26. package/dist/event-streams-UU2VASBU.js.map +1 -0
  27. package/dist/index.d.ts +0 -3
  28. package/dist/index.js +233 -342
  29. package/dist/index.js.map +1 -1
  30. package/dist/{loadSso-GOLDOL76.js → loadSso-SCNBGUAS.js} +8 -8
  31. package/dist/{signin-TS4P2IEW.js → signin-6CO4ELBM.js} +8 -8
  32. package/dist/{sso-oidc-QHNBBLAM.js → sso-oidc-NYPIZEZ2.js} +8 -8
  33. package/dist/{sts-ZKQ7LNEG.js → sts-7LYERIMP.js} +8 -8
  34. package/package.json +6 -6
  35. package/dist/chunk-GPJBZ6EG.js.map +0 -1
  36. package/dist/chunk-RBRHTAJN.js.map +0 -1
  37. package/dist/chunk-RKAR27K2.js.map +0 -1
  38. package/dist/chunk-Y62BMZ25.js.map +0 -1
  39. package/dist/chunk-YYVVWLB2.js.map +0 -1
  40. package/dist/dist-es-BGEPUOPB.js.map +0 -1
  41. package/dist/event-streams-2HBIXE6X.js.map +0 -1
  42. /package/dist/{chunk-RRZDPP7Z.js.map → chunk-X77CPJUJ.js.map} +0 -0
  43. /package/dist/{chunk-UKT6IXAM.js.map → chunk-XTHXGGIJ.js.map} +0 -0
  44. /package/dist/{dist-es-TLOL2VHU.js.map → dist-es-BSJRQ6XP.js.map} +0 -0
  45. /package/dist/{dist-es-BUTLC2YS.js.map → dist-es-C2VXNLLU.js.map} +0 -0
  46. /package/dist/{dist-es-M72B762W.js.map → dist-es-FTEZAK7G.js.map} +0 -0
  47. /package/dist/{dist-es-NGG7JHEH.js.map → dist-es-FV5JDCUX.js.map} +0 -0
  48. /package/dist/{dist-es-WLYFLMD3.js.map → dist-es-IS4IC3TZ.js.map} +0 -0
  49. /package/dist/{dist-es-ILOZ33QI.js.map → dist-es-ISXX5KU4.js.map} +0 -0
  50. /package/dist/{dist-es-WS6NDSQ5.js.map → dist-es-RR4OU64S.js.map} +0 -0
  51. /package/dist/{dist-es-LN4LZWKV.js.map → dist-es-V7467ELV.js.map} +0 -0
  52. /package/dist/{loadSso-GOLDOL76.js.map → loadSso-SCNBGUAS.js.map} +0 -0
  53. /package/dist/{signin-TS4P2IEW.js.map → signin-6CO4ELBM.js.map} +0 -0
  54. /package/dist/{sso-oidc-QHNBBLAM.js.map → sso-oidc-NYPIZEZ2.js.map} +0 -0
  55. /package/dist/{sts-ZKQ7LNEG.js.map → sts-7LYERIMP.js.map} +0 -0
package/dist/index.js CHANGED
@@ -57,9 +57,107 @@ function queryResources(all, filter) {
57
57
 
58
58
  // src/implementations/neptune.ts
59
59
  import { getEntityTypes } from "@semiont/ontology";
60
+
61
+ // src/annotation-codec.ts
60
62
  import { annotationId as makeAnnotationId } from "@semiont/core";
63
+ import { getBodySource, getExactText, getTargetSelector, getTargetSource } from "@semiont/core";
64
+ function storedAnnotationType(motivation) {
65
+ return motivation === "highlighting" ? "TextualBody" : "SpecificResource";
66
+ }
67
+ function motivationForCategory(category) {
68
+ return category === "highlight" ? "highlighting" : "linking";
69
+ }
70
+ function buildAnnotation(input, created) {
71
+ const annotation = {
72
+ "@context": "http://www.w3.org/ns/anno.jsonld",
73
+ type: "Annotation",
74
+ id: makeAnnotationId(input.id),
75
+ motivation: input.motivation,
76
+ target: input.target,
77
+ creator: input.creator,
78
+ created
79
+ };
80
+ if (input.body && (!Array.isArray(input.body) || input.body.length > 0)) {
81
+ annotation.body = input.body;
82
+ }
83
+ return annotation;
84
+ }
85
+ function encodeAnnotation(annotation) {
86
+ const selector = getTargetSelector(annotation.target);
87
+ const bodySource = getBodySource(annotation.body);
88
+ const resourceId = getTargetSource(annotation.target);
89
+ if (!resourceId) throw new Error(`Annotation ${annotation.id} has no target source`);
90
+ if (!annotation.created) throw new Error(`Annotation ${annotation.id} has no created timestamp`);
91
+ const props = {
92
+ id: annotation.id,
93
+ resourceId,
94
+ type: storedAnnotationType(annotation.motivation),
95
+ motivation: annotation.motivation,
96
+ creator: JSON.stringify(annotation.creator),
97
+ created: annotation.created
98
+ };
99
+ if (selector) Object.assign(props, encodeSelector(selector));
100
+ if (bodySource) props.source = bodySource;
101
+ if (annotation.modified) props.modified = annotation.modified;
102
+ if (annotation.generator) props.generator = JSON.stringify(annotation.generator);
103
+ return props;
104
+ }
105
+ function encodeSelector(selector) {
106
+ const props = { selector: JSON.stringify(selector) };
107
+ const exact = getExactText(selector);
108
+ if (exact) props.exact = exact;
109
+ return props;
110
+ }
111
+ function decodeAnnotation(props, entityTypes = []) {
112
+ const id = props.id;
113
+ if (!id) throw new Error("Annotation missing required field: id");
114
+ const required = (key) => {
115
+ const value = props[key];
116
+ if (!value) throw new Error(`Annotation ${id} missing required field: ${key}`);
117
+ return value;
118
+ };
119
+ const resourceId = required("resourceId");
120
+ const creator = JSON.parse(required("creator"));
121
+ const motivation = required("motivation");
122
+ const created = required("created");
123
+ const body = [];
124
+ for (const entityType of entityTypes) {
125
+ if (entityType) body.push({ type: "TextualBody", value: entityType, purpose: "tagging" });
126
+ }
127
+ if (props.source) {
128
+ body.push({ type: "SpecificResource", source: props.source, purpose: "linking" });
129
+ }
130
+ const selector = decodeSelector(props.selector);
131
+ const target = selector ? { source: resourceId, selector } : { source: resourceId };
132
+ const annotation = {
133
+ "@context": "http://www.w3.org/ns/anno.jsonld",
134
+ type: "Annotation",
135
+ id: makeAnnotationId(id),
136
+ motivation,
137
+ target,
138
+ creator,
139
+ created
140
+ };
141
+ if (body.length > 0) annotation.body = body;
142
+ if (props.modified) annotation.modified = props.modified;
143
+ if (props.generator) {
144
+ try {
145
+ annotation.generator = JSON.parse(props.generator);
146
+ } catch {
147
+ }
148
+ }
149
+ return annotation;
150
+ }
151
+ function decodeSelector(raw) {
152
+ if (!raw) return void 0;
153
+ const parsed = JSON.parse(raw);
154
+ if (!parsed || Object.keys(parsed).length === 0) return void 0;
155
+ return parsed;
156
+ }
157
+
158
+ // src/implementations/neptune.ts
61
159
  import { v4 as uuidv4 } from "uuid";
62
- import { getBodySource, getExactText, getTargetSource, getTargetSelector, getPrimaryRepresentation, getResourceId } from "@semiont/core";
160
+ import { getBodySource as getBodySource2, getTargetSource as getTargetSource2, getPrimaryRepresentation, getResourceId } from "@semiont/core";
63
161
  var NeptuneClient;
64
162
  var DescribeDBClustersCommand;
65
163
  var gremlin;
@@ -69,7 +167,7 @@ var cardinality;
69
167
  var __;
70
168
  async function loadDependencies() {
71
169
  if (!NeptuneClient) {
72
- const neptuneModule = await import("./dist-es-BGEPUOPB.js");
170
+ const neptuneModule = await import("./dist-es-AET2QNVA.js");
73
171
  NeptuneClient = neptuneModule.NeptuneClient;
74
172
  DescribeDBClustersCommand = neptuneModule.DescribeDBClustersCommand;
75
173
  }
@@ -125,70 +223,22 @@ function vertexToResource(vertex) {
125
223
  return resource;
126
224
  }
127
225
  function vertexToAnnotation(vertex, entityTypes = []) {
128
- const props = vertex.properties || vertex;
129
- const getValue = (key, required = false) => {
130
- const prop = props[key];
131
- if (!prop) {
132
- if (required) {
133
- throw new Error(`Annotation ${vertex.id || "unknown"} missing required field: ${key}`);
134
- }
135
- return void 0;
136
- }
137
- if (Array.isArray(prop) && prop.length > 0) {
138
- return prop[0].value !== void 0 ? prop[0].value : prop[0];
139
- }
140
- if (typeof prop === "object" && "value" in prop) return prop.value;
141
- return prop;
142
- };
143
- const id = getValue("id", true);
144
- const resourceId = getValue("resourceId", true);
145
- const selectorRaw = getValue("selector", true);
146
- const creatorRaw = getValue("creator", true);
147
- const createdRaw = getValue("created", true);
148
- const motivation = getValue("motivation") || "linking";
149
- const creator = JSON.parse(creatorRaw);
150
- const bodyArray = [];
151
- for (const entityType of entityTypes) {
152
- if (entityType) {
153
- bodyArray.push({
154
- type: "TextualBody",
155
- value: entityType,
156
- purpose: "tagging"
157
- });
158
- }
159
- }
160
- const bodySource = getValue("source");
161
- if (bodySource) {
162
- bodyArray.push({
163
- type: "SpecificResource",
164
- source: bodySource,
165
- purpose: "linking"
166
- });
167
- }
168
- const annotation = {
169
- "@context": "http://www.w3.org/ns/anno.jsonld",
170
- "type": "Annotation",
171
- id,
172
- motivation,
173
- target: {
174
- source: resourceId,
175
- selector: JSON.parse(selectorRaw)
176
- },
177
- body: bodyArray,
178
- creator,
179
- created: createdRaw
180
- // ISO string from DB
181
- };
182
- const modified = getValue("modified");
183
- if (modified) annotation.modified = modified;
184
- const generatorJson = getValue("generator");
185
- if (generatorJson) {
186
- try {
187
- annotation.generator = JSON.parse(generatorJson);
188
- } catch (e) {
189
- }
190
- }
191
- return annotation;
226
+ return decodeAnnotation(normalizeProperties(vertex.properties || vertex), entityTypes);
227
+ }
228
+ function normalizeProperties(props) {
229
+ const normalized = {};
230
+ for (const [key, raw] of Object.entries(props ?? {})) {
231
+ const value = unwrap(raw);
232
+ if (value === void 0 || value === null) continue;
233
+ normalized[key] = typeof value === "string" ? value : String(value);
234
+ }
235
+ return normalized;
236
+ }
237
+ function unwrap(prop) {
238
+ if (prop === void 0 || prop === null) return void 0;
239
+ if (Array.isArray(prop)) return prop.length > 0 ? unwrap(prop[0]) : void 0;
240
+ if (typeof prop === "object" && "value" in prop) return prop.value;
241
+ return prop;
192
242
  }
193
243
  var NeptuneGraphDatabase = class {
194
244
  connected = false;
@@ -385,25 +435,15 @@ var NeptuneGraphDatabase = class {
385
435
  }
386
436
  }
387
437
  async createAnnotation(input) {
388
- const id = input.id;
389
- const annotation = {
390
- "@context": "http://www.w3.org/ns/anno.jsonld",
391
- "type": "Annotation",
392
- id: makeAnnotationId(id),
393
- motivation: input.motivation,
394
- target: input.target,
395
- body: input.body,
396
- creator: input.creator,
397
- created: (/* @__PURE__ */ new Date()).toISOString()
398
- };
399
- const targetSource = getTargetSource(input.target);
400
- const targetSelector = getTargetSelector(input.target);
401
- const bodySource = getBodySource(input.body);
438
+ const annotation = buildAnnotation(input, (/* @__PURE__ */ new Date()).toISOString());
439
+ const props = encodeAnnotation(annotation);
440
+ const targetSource = props.resourceId;
441
+ const bodySource = props.source;
402
442
  const entityTypes = getEntityTypes(input);
403
443
  try {
404
- const vertex = this.g.addV("Annotation").property("id", annotation.id).property("resourceId", targetSource).property("text", targetSelector ? getExactText(targetSelector) : "").property("selector", JSON.stringify(targetSelector || {})).property("type", "SpecificResource").property("motivation", annotation.motivation).property("creator", JSON.stringify(annotation.creator)).property("created", annotation.created);
405
- if (bodySource) {
406
- vertex.property("source", bodySource);
444
+ let vertex = this.g.addV("Annotation");
445
+ for (const [key, value] of Object.entries(props)) {
446
+ vertex = vertex.property(key, value);
407
447
  }
408
448
  const newVertex = await vertex.next();
409
449
  await this.g.V(newVertex.value).addE("BELONGS_TO").to(this.g.V().hasLabel("Resource").has("id", targetSource)).next();
@@ -443,11 +483,13 @@ var NeptuneGraphDatabase = class {
443
483
  let traversal = this.g.V().hasLabel("Annotation").has("id", id);
444
484
  if (updates.target !== void 0 && typeof updates.target !== "string") {
445
485
  if (updates.target.selector !== void 0) {
446
- traversal = traversal.property("text", getExactText(updates.target.selector));
486
+ for (const [key, value] of Object.entries(encodeSelector(updates.target.selector))) {
487
+ traversal = traversal.property(key, value);
488
+ }
447
489
  }
448
490
  }
449
491
  if (updates.body !== void 0) {
450
- const bodySource = getBodySource(updates.body);
492
+ const bodySource = getBodySource2(updates.body);
451
493
  const entityTypes2 = getEntityTypes({ body: updates.body });
452
494
  if (bodySource) {
453
495
  traversal = traversal.property("source", bodySource);
@@ -497,8 +539,7 @@ var NeptuneGraphDatabase = class {
497
539
  traversal = traversal.has("resourceId", filter.resourceId);
498
540
  }
499
541
  if (filter.type) {
500
- const w3cType = filter.type === "highlight" ? "TextualBody" : "SpecificResource";
501
- traversal = traversal.has("type", w3cType);
542
+ traversal = traversal.has("type", storedAnnotationType(motivationForCategory(filter.type)));
502
543
  }
503
544
  const results = await traversal.elementMap().toList();
504
545
  const annotations = await this.fetchAnnotationsWithEntityTypes(results);
@@ -592,7 +633,7 @@ var NeptuneGraphDatabase = class {
592
633
  const entityTypesResult = await this.g.V().hasLabel("Annotation").has("id", id).out("TAGGED_AS").hasLabel("EntityType").values("name").toList();
593
634
  const entityTypes = entityTypesResult || [];
594
635
  const annotation = vertexToAnnotation(annVertex, entityTypes);
595
- const targetDocId = getBodySource(annotation.body);
636
+ const targetDocId = getBodySource2(annotation.body);
596
637
  if (!targetDocId) continue;
597
638
  const targetDocResult = await this.g.V().hasLabel("Resource").has("id", targetDocId).elementMap().next();
598
639
  if (targetDocResult.value) {
@@ -616,7 +657,7 @@ var NeptuneGraphDatabase = class {
616
657
  const entityTypesResult = await this.g.V().hasLabel("Annotation").has("id", id).out("TAGGED_AS").hasLabel("EntityType").values("name").toList();
617
658
  const entityTypes = entityTypesResult || [];
618
659
  const annotation = vertexToAnnotation(annVertex, entityTypes);
619
- const sourceDocId = getTargetSource(annotation.target);
660
+ const sourceDocId = getTargetSource2(annotation.target);
620
661
  const existing = connectionsMap.get(sourceDocId);
621
662
  if (existing) {
622
663
  existing.bidirectional = true;
@@ -820,9 +861,8 @@ var NeptuneGraphDatabase = class {
820
861
  };
821
862
 
822
863
  // src/implementations/neo4j.ts
823
- import { annotationId as makeAnnotationId2 } from "@semiont/core";
824
864
  import { v4 as uuidv42 } from "uuid";
825
- import { getExactText as getExactText2, getBodySource as getBodySource2, getTargetSource as getTargetSource2, getTargetSelector as getTargetSelector2, getPrimaryRepresentation as getPrimaryRepresentation2 } from "@semiont/core";
865
+ import { getPrimaryRepresentation as getPrimaryRepresentation2 } from "@semiont/core";
826
866
  import { getEntityTypes as getEntityTypes2 } from "@semiont/ontology";
827
867
  function motivationToLabel(motivation) {
828
868
  return motivation.charAt(0).toUpperCase() + motivation.slice(1);
@@ -1089,85 +1129,42 @@ var Neo4jGraphDatabase = class {
1089
1129
  async createAnnotation(input) {
1090
1130
  const session = this.getSession();
1091
1131
  try {
1092
- const id = input.id;
1093
- const annotation = {
1094
- "@context": "http://www.w3.org/ns/anno.jsonld",
1095
- "type": "Annotation",
1096
- id: makeAnnotationId2(id),
1097
- motivation: input.motivation,
1098
- target: input.target,
1099
- body: input.body,
1100
- creator: input.creator,
1101
- created: (/* @__PURE__ */ new Date()).toISOString()
1102
- };
1103
- const targetSource = getTargetSource2(input.target);
1104
- const targetSelector = getTargetSelector2(input.target);
1105
- const bodySource = getBodySource2(input.body);
1132
+ const annotation = buildAnnotation(input, (/* @__PURE__ */ new Date()).toISOString());
1133
+ const props = encodeAnnotation(annotation);
1134
+ const targetSource = props.resourceId;
1135
+ const bodySource = props.source;
1106
1136
  const entityTypes = getEntityTypes2(input);
1107
1137
  const motivationLabel = motivationToLabel(annotation.motivation);
1108
- let cypher;
1109
- if (bodySource) {
1110
- cypher = `MATCH (from:Resource {id: $fromId})
1111
- MATCH (to:Resource {id: $toId})
1112
- CREATE (a:Annotation:${motivationLabel} {
1113
- id: $id,
1114
- resourceId: $resourceId,
1115
- exact: $exact,
1116
- selector: $selector,
1117
- type: $type,
1118
- motivation: $motivation,
1119
- creator: $creator,
1120
- created: datetime($created),
1121
- source: $source
1122
- })
1138
+ const cypher = bodySource ? `MATCH (from:Resource {id: $targetSource})
1139
+ MATCH (to:Resource {id: $bodySource})
1140
+ CREATE (a:Annotation:${motivationLabel})
1141
+ SET a = $props, a.created = datetime($created)
1123
1142
  CREATE (a)-[:BELONGS_TO]->(from)
1124
1143
  CREATE (a)-[:REFERENCES]->(to)
1125
1144
  FOREACH (entityType IN $entityTypes |
1126
1145
  MERGE (et:EntityType {name: entityType})
1127
1146
  CREATE (a)-[:TAGGED_AS]->(et)
1128
1147
  )
1129
- RETURN a`;
1130
- } else {
1131
- cypher = `MATCH (d:Resource {id: $resourceId})
1132
- CREATE (a:Annotation:${motivationLabel} {
1133
- id: $id,
1134
- resourceId: $resourceId,
1135
- exact: $exact,
1136
- selector: $selector,
1137
- type: $type,
1138
- motivation: $motivation,
1139
- creator: $creator,
1140
- created: datetime($created)
1141
- })
1148
+ RETURN a` : `MATCH (d:Resource {id: $targetSource})
1149
+ CREATE (a:Annotation:${motivationLabel})
1150
+ SET a = $props, a.created = datetime($created)
1142
1151
  CREATE (a)-[:BELONGS_TO]->(d)
1143
1152
  FOREACH (entityType IN $entityTypes |
1144
1153
  MERGE (et:EntityType {name: entityType})
1145
1154
  CREATE (a)-[:TAGGED_AS]->(et)
1146
1155
  )
1147
1156
  RETURN a`;
1148
- }
1149
- const params = {
1150
- id,
1151
- resourceId: targetSource,
1152
- // Store full URI
1153
- fromId: targetSource,
1154
- // Store full URI
1155
- toId: bodySource || null,
1156
- // Store full URI
1157
- exact: targetSelector ? getExactText2(targetSelector) : "",
1158
- selector: JSON.stringify(targetSelector || {}),
1159
- type: "SpecificResource",
1160
- motivation: annotation.motivation,
1161
- creator: JSON.stringify(annotation.creator),
1157
+ const result = await session.run(cypher, {
1158
+ props,
1162
1159
  created: annotation.created,
1163
- entityTypes,
1164
- source: bodySource || null
1165
- };
1166
- const result = await session.run(cypher, params);
1160
+ targetSource,
1161
+ bodySource: bodySource ?? null,
1162
+ entityTypes
1163
+ });
1167
1164
  if (result.records.length === 0) {
1168
1165
  throw new Error(`Failed to create annotation: Resource ${targetSource} not found in graph database`);
1169
1166
  }
1170
- return this.parseAnnotationNode(result.records[0].get("a"), entityTypes);
1167
+ return parseAnnotationNode(result.records[0].get("a"), entityTypes);
1171
1168
  } finally {
1172
1169
  await session.close();
1173
1170
  }
@@ -1187,7 +1184,7 @@ var Neo4jGraphDatabase = class {
1187
1184
  return null;
1188
1185
  }
1189
1186
  this.logger?.debug("Annotation found", { id });
1190
- return this.parseAnnotationNode(
1187
+ return parseAnnotationNode(
1191
1188
  result.records[0].get("a"),
1192
1189
  result.records[0].get("entityTypes")
1193
1190
  );
@@ -1203,9 +1200,9 @@ var Neo4jGraphDatabase = class {
1203
1200
  Object.entries(updates).forEach(([key, value]) => {
1204
1201
  if (key !== "id" && key !== "updatedAt") {
1205
1202
  setClauses.push(`a.${key} = $${key}`);
1206
- if (key === "selector" || key === "metadata" || key === "body") {
1203
+ if (key === "body") {
1207
1204
  params[key] = JSON.stringify(value);
1208
- } else if (key === "created" || key === "resolvedAt") {
1205
+ } else if (key === "created") {
1209
1206
  params[key] = value ? new Date(value).toISOString() : null;
1210
1207
  } else {
1211
1208
  params[key] = value;
@@ -1283,7 +1280,7 @@ var Neo4jGraphDatabase = class {
1283
1280
  } else {
1284
1281
  this.logger?.debug("No body update for annotation", { id });
1285
1282
  }
1286
- return this.parseAnnotationNode(
1283
+ return parseAnnotationNode(
1287
1284
  result.records[0].get("a"),
1288
1285
  result.records[0].get("entityTypes")
1289
1286
  );
@@ -1312,9 +1309,8 @@ var Neo4jGraphDatabase = class {
1312
1309
  params.resourceId = filter.resourceId;
1313
1310
  }
1314
1311
  if (filter.type) {
1315
- const w3cType = filter.type === "highlight" ? "TextualBody" : "SpecificResource";
1316
1312
  conditions.push("a.type = $type");
1317
- params.type = w3cType;
1313
+ params.type = storedAnnotationType(motivationForCategory(filter.type));
1318
1314
  }
1319
1315
  const whereClause = conditions.length > 0 ? "WHERE " + conditions.join(" AND ") : "";
1320
1316
  const result = await session.run(
@@ -1324,7 +1320,7 @@ var Neo4jGraphDatabase = class {
1324
1320
  params
1325
1321
  );
1326
1322
  const annotations = result.records.map(
1327
- (record) => this.parseAnnotationNode(record.get("a"), record.get("entityTypes"))
1323
+ (record) => parseAnnotationNode(record.get("a"), record.get("entityTypes"))
1328
1324
  );
1329
1325
  return { annotations, total: annotations.length };
1330
1326
  } finally {
@@ -1343,7 +1339,7 @@ var Neo4jGraphDatabase = class {
1343
1339
  { resourceId }
1344
1340
  );
1345
1341
  return result.records.map(
1346
- (record) => this.parseAnnotationNode(record.get("a"), record.get("entityTypes"))
1342
+ (record) => parseAnnotationNode(record.get("a"), record.get("entityTypes"))
1347
1343
  );
1348
1344
  } finally {
1349
1345
  await session.close();
@@ -1371,7 +1367,7 @@ var Neo4jGraphDatabase = class {
1371
1367
  if (result.records.length === 0) {
1372
1368
  throw new Error("Annotation not found");
1373
1369
  }
1374
- return this.parseAnnotationNode(
1370
+ return parseAnnotationNode(
1375
1371
  result.records[0].get("a"),
1376
1372
  result.records[0].get("entityTypes")
1377
1373
  );
@@ -1391,7 +1387,7 @@ var Neo4jGraphDatabase = class {
1391
1387
  { resourceId }
1392
1388
  );
1393
1389
  return result.records.map(
1394
- (record) => this.parseAnnotationNode(record.get("a"), record.get("entityTypes"))
1390
+ (record) => parseAnnotationNode(record.get("a"), record.get("entityTypes"))
1395
1391
  );
1396
1392
  } finally {
1397
1393
  await session.close();
@@ -1415,7 +1411,7 @@ var Neo4jGraphDatabase = class {
1415
1411
  ORDER BY a.created DESC`;
1416
1412
  const result = await session.run(cypher, params);
1417
1413
  return result.records.map(
1418
- (record) => this.parseAnnotationNode(record.get("a"), record.get("entityTypes"))
1414
+ (record) => parseAnnotationNode(record.get("a"), record.get("entityTypes"))
1419
1415
  );
1420
1416
  } finally {
1421
1417
  await session.close();
@@ -1432,7 +1428,7 @@ var Neo4jGraphDatabase = class {
1432
1428
  { resourceId }
1433
1429
  );
1434
1430
  return result.records.map(
1435
- (record) => this.parseAnnotationNode(record.get("a"), record.get("entityTypes"))
1431
+ (record) => parseAnnotationNode(record.get("a"), record.get("entityTypes"))
1436
1432
  );
1437
1433
  } finally {
1438
1434
  await session.close();
@@ -1450,7 +1446,7 @@ var Neo4jGraphDatabase = class {
1450
1446
  const result = await session.run(cypher, { resourceId });
1451
1447
  this.logger?.debug("Found annotations", { count: result.records.length });
1452
1448
  return result.records.map(
1453
- (record) => this.parseAnnotationNode(record.get("a"), record.get("entityTypes"))
1449
+ (record) => parseAnnotationNode(record.get("a"), record.get("entityTypes"))
1454
1450
  );
1455
1451
  } finally {
1456
1452
  await session.close();
@@ -1482,7 +1478,7 @@ var Neo4jGraphDatabase = class {
1482
1478
  { id: annId }
1483
1479
  );
1484
1480
  if (annResult.records.length > 0) {
1485
- outgoing.push(this.parseAnnotationNode(
1481
+ outgoing.push(parseAnnotationNode(
1486
1482
  annResult.records[0].get("a"),
1487
1483
  annResult.records[0].get("entityTypes")
1488
1484
  ));
@@ -1499,7 +1495,7 @@ var Neo4jGraphDatabase = class {
1499
1495
  { id: annId }
1500
1496
  );
1501
1497
  if (annResult.records.length > 0) {
1502
- incoming.push(this.parseAnnotationNode(
1498
+ incoming.push(parseAnnotationNode(
1503
1499
  annResult.records[0].get("a"),
1504
1500
  annResult.records[0].get("entityTypes")
1505
1501
  ));
@@ -1540,7 +1536,7 @@ var Neo4jGraphDatabase = class {
1540
1536
  { ids: annotationIds }
1541
1537
  );
1542
1538
  selResult.records.forEach((rec) => {
1543
- annotations.push(this.parseAnnotationNode(
1539
+ annotations.push(parseAnnotationNode(
1544
1540
  rec.get("a"),
1545
1541
  rec.get("entityTypes")
1546
1542
  ));
@@ -1777,62 +1773,39 @@ var Neo4jGraphDatabase = class {
1777
1773
  if (props.storageUri) resource.storageUri = props.storageUri;
1778
1774
  return resource;
1779
1775
  }
1780
- parseAnnotationNode(node, entityTypes = []) {
1781
- const props = node.properties;
1782
- if (!props.id) throw new Error("Annotation missing required field: id");
1783
- if (!props.resourceId) throw new Error(`Annotation ${props.id} missing required field: resourceId`);
1784
- if (!props.type) throw new Error(`Annotation ${props.id} missing required field: type`);
1785
- if (!props.selector) throw new Error(`Annotation ${props.id} missing required field: selector`);
1786
- if (!props.creator) throw new Error(`Annotation ${props.id} missing required field: creator`);
1787
- if (!props.motivation) throw new Error(`Annotation ${props.id} missing required field: motivation`);
1788
- const creator = JSON.parse(props.creator);
1789
- const bodyArray = [];
1790
- for (const entityType of entityTypes) {
1791
- if (entityType) {
1792
- bodyArray.push({
1793
- type: "TextualBody",
1794
- value: entityType,
1795
- purpose: "tagging"
1796
- });
1797
- }
1798
- }
1799
- if (props.source) {
1800
- bodyArray.push({
1801
- type: "SpecificResource",
1802
- source: props.source,
1803
- purpose: "linking"
1804
- });
1805
- }
1806
- const annotation = {
1807
- "@context": "http://www.w3.org/ns/anno.jsonld",
1808
- "type": "Annotation",
1809
- id: props.id,
1810
- motivation: props.motivation,
1811
- target: {
1812
- source: props.resourceId,
1813
- selector: JSON.parse(props.selector)
1814
- },
1815
- body: bodyArray,
1816
- creator,
1817
- created: props.created
1818
- // ISO string from DB
1819
- };
1820
- if (props.modified) annotation.modified = props.modified.toString();
1821
- if (props.generator) {
1822
- try {
1823
- annotation.generator = JSON.parse(props.generator);
1824
- } catch (e) {
1825
- }
1826
- }
1827
- return annotation;
1828
- }
1829
1776
  };
1777
+ function parseAnnotationNode(node, entityTypes = []) {
1778
+ return decodeAnnotation(normalizeProperties2(node.properties), entityTypes);
1779
+ }
1780
+ function normalizeProperties2(props) {
1781
+ const normalized = {};
1782
+ for (const [key, value] of Object.entries(props ?? {})) {
1783
+ if (value === null || value === void 0) continue;
1784
+ normalized[key] = typeof value === "string" ? value : String(value);
1785
+ }
1786
+ return normalized;
1787
+ }
1830
1788
 
1831
1789
  // src/implementations/janusgraph.ts
1832
- import { resourceId as makeResourceId, annotationId as makeAnnotationId3 } from "@semiont/core";
1833
- import { getBodySource as getBodySource3, getPrimaryRepresentation as getPrimaryRepresentation3, getResourceId as getResourceId2, getExactText as getExactText3 } from "@semiont/core";
1790
+ import { resourceId as makeResourceId } from "@semiont/core";
1791
+ import { getBodySource as getBodySource3, getPrimaryRepresentation as getPrimaryRepresentation3, getResourceId as getResourceId2 } from "@semiont/core";
1834
1792
  import { getEntityTypes as getEntityTypes3 } from "@semiont/ontology";
1835
1793
  import { v4 as uuidv43 } from "uuid";
1794
+ function getPropertyValue(props, key) {
1795
+ if (!props[key]) return void 0;
1796
+ const prop = Array.isArray(props[key]) ? props[key][0] : props[key];
1797
+ return prop?.value || prop;
1798
+ }
1799
+ function vertexToAnnotation2(vertex, entityTypes = []) {
1800
+ const props = vertex.properties || {};
1801
+ const normalized = {};
1802
+ for (const key of Object.keys(props)) {
1803
+ const value = getPropertyValue(props, key);
1804
+ if (value === void 0 || value === null) continue;
1805
+ normalized[key] = typeof value === "string" ? value : String(value);
1806
+ }
1807
+ return decodeAnnotation(normalized, entityTypes);
1808
+ }
1836
1809
  var JanusGraphDatabase = class {
1837
1810
  constructor(graphConfig) {
1838
1811
  this.graphConfig = graphConfig;
@@ -1883,10 +1856,10 @@ var JanusGraphDatabase = class {
1883
1856
  // Helper function to convert vertex to Resource
1884
1857
  vertexToResource(vertex) {
1885
1858
  const props = vertex.properties || {};
1886
- const id = this.getPropertyValue(props, "id");
1887
- const creatorRaw = this.getPropertyValue(props, "creator");
1888
- const contentChecksum = this.getPropertyValue(props, "contentChecksum");
1889
- const mediaType = this.getPropertyValue(props, "contentType");
1859
+ const id = getPropertyValue(props, "id");
1860
+ const creatorRaw = getPropertyValue(props, "creator");
1861
+ const contentChecksum = getPropertyValue(props, "contentChecksum");
1862
+ const mediaType = getPropertyValue(props, "contentType");
1890
1863
  if (!creatorRaw) throw new Error(`Resource ${id} missing required field: creator`);
1891
1864
  if (!contentChecksum) throw new Error(`Resource ${id} missing required field: contentChecksum`);
1892
1865
  if (!mediaType) throw new Error(`Resource ${id} missing required field: contentType`);
@@ -1894,95 +1867,38 @@ var JanusGraphDatabase = class {
1894
1867
  const resource = {
1895
1868
  "@context": "https://schema.org/",
1896
1869
  "@id": id,
1897
- name: this.getPropertyValue(props, "name"),
1898
- entityTypes: JSON.parse(this.getPropertyValue(props, "entityTypes") || "[]"),
1870
+ name: getPropertyValue(props, "name"),
1871
+ entityTypes: JSON.parse(getPropertyValue(props, "entityTypes") || "[]"),
1899
1872
  representations: [{
1900
1873
  mediaType,
1901
1874
  checksum: contentChecksum,
1902
1875
  rel: "original"
1903
1876
  }],
1904
- archived: this.getPropertyValue(props, "archived") === "true",
1905
- dateCreated: this.getPropertyValue(props, "created"),
1877
+ archived: getPropertyValue(props, "archived") === "true",
1878
+ dateCreated: getPropertyValue(props, "created"),
1906
1879
  wasAttributedTo: creator
1907
1880
  };
1908
- const sourceAnnotationId = this.getPropertyValue(props, "sourceAnnotationId");
1909
- const sourceResourceId = this.getPropertyValue(props, "sourceResourceId");
1910
- const storageUri = this.getPropertyValue(props, "storageUri");
1881
+ const sourceAnnotationId = getPropertyValue(props, "sourceAnnotationId");
1882
+ const sourceResourceId = getPropertyValue(props, "sourceResourceId");
1883
+ const storageUri = getPropertyValue(props, "storageUri");
1911
1884
  if (sourceAnnotationId) resource.sourceAnnotationId = sourceAnnotationId;
1912
1885
  if (sourceResourceId) resource.sourceResourceId = sourceResourceId;
1913
1886
  if (storageUri) resource.storageUri = storageUri;
1914
1887
  return resource;
1915
1888
  }
1916
- // Helper to get property value from Gremlin vertex properties
1917
- getPropertyValue(props, key) {
1918
- if (!props[key]) return void 0;
1919
- const prop = Array.isArray(props[key]) ? props[key][0] : props[key];
1920
- return prop?.value || prop;
1921
- }
1922
1889
  // Helper method to fetch annotations with their entity types
1923
1890
  async fetchAnnotationsWithEntityTypes(annotationVertices) {
1924
1891
  const annotations = [];
1925
1892
  for (const vertex of annotationVertices) {
1926
- const id = this.getPropertyValue(vertex.properties || {}, "id");
1893
+ const id = getPropertyValue(vertex.properties || {}, "id");
1927
1894
  const entityTypeVertices = await this.g.V().has("Annotation", "id", id).out("TAGGED_AS").has("EntityType").toList();
1928
1895
  const entityTypes = entityTypeVertices.map(
1929
- (v) => this.getPropertyValue(v.properties || {}, "name")
1896
+ (v) => getPropertyValue(v.properties || {}, "name")
1930
1897
  ).filter(Boolean);
1931
- annotations.push(this.vertexToAnnotation(vertex, entityTypes));
1898
+ annotations.push(vertexToAnnotation2(vertex, entityTypes));
1932
1899
  }
1933
1900
  return annotations;
1934
1901
  }
1935
- // Helper function to convert vertex to Annotation
1936
- vertexToAnnotation(vertex, entityTypes = []) {
1937
- const props = vertex.properties || {};
1938
- const motivation = this.getPropertyValue(props, "motivation") || "linking";
1939
- const creatorJson = this.getPropertyValue(props, "creator");
1940
- const creator = JSON.parse(creatorJson);
1941
- const bodyArray = [];
1942
- for (const entityType of entityTypes) {
1943
- if (entityType) {
1944
- bodyArray.push({
1945
- type: "TextualBody",
1946
- value: entityType,
1947
- purpose: "tagging"
1948
- });
1949
- }
1950
- }
1951
- const bodySource = this.getPropertyValue(props, "source");
1952
- if (bodySource) {
1953
- bodyArray.push({
1954
- type: "SpecificResource",
1955
- source: bodySource,
1956
- purpose: "linking"
1957
- });
1958
- }
1959
- const annotation = {
1960
- "@context": "http://www.w3.org/ns/anno.jsonld",
1961
- "type": "Annotation",
1962
- id: this.getPropertyValue(props, "id"),
1963
- motivation,
1964
- target: {
1965
- source: this.getPropertyValue(props, "resourceId"),
1966
- selector: JSON.parse(this.getPropertyValue(props, "selector") || "{}")
1967
- },
1968
- body: bodyArray,
1969
- creator,
1970
- created: this.getPropertyValue(props, "created")
1971
- // ISO string from DB
1972
- };
1973
- const modified = this.getPropertyValue(props, "modified");
1974
- if (modified) {
1975
- annotation.modified = modified;
1976
- }
1977
- const generatorJson = this.getPropertyValue(props, "generator");
1978
- if (generatorJson) {
1979
- try {
1980
- annotation.generator = JSON.parse(generatorJson);
1981
- } catch (e) {
1982
- }
1983
- }
1984
- return annotation;
1985
- }
1986
1902
  async createResource(resource) {
1987
1903
  const id = getResourceId2(resource);
1988
1904
  const primaryRep = getPrimaryRepresentation3(resource);
@@ -2035,26 +1951,14 @@ var JanusGraphDatabase = class {
2035
1951
  return queryResources(docs.map((v) => this.vertexToResource(v)), filter);
2036
1952
  }
2037
1953
  async createAnnotation(input) {
2038
- const id = input.id;
2039
- const motivation = input.motivation;
2040
- const annotation = {
2041
- "@context": "http://www.w3.org/ns/anno.jsonld",
2042
- "type": "Annotation",
2043
- id: makeAnnotationId3(id),
2044
- motivation,
2045
- target: input.target,
2046
- body: input.body,
2047
- creator: input.creator,
2048
- created: (/* @__PURE__ */ new Date()).toISOString()
2049
- };
2050
- const bodySource = getBodySource3(input.body);
1954
+ const annotation = buildAnnotation(input, (/* @__PURE__ */ new Date()).toISOString());
1955
+ const props = encodeAnnotation(annotation);
1956
+ const targetSource = props.resourceId;
1957
+ const bodySource = props.source;
2051
1958
  const entityTypes = getEntityTypes3(input);
2052
- const bodyType = input.body === void 0 ? "None" : Array.isArray(input.body) ? "SpecificResource" : input.body.type;
2053
- const targetSource = typeof input.target === "string" ? input.target : input.target.source;
2054
- const targetSelector = typeof input.target === "string" ? void 0 : input.target.selector;
2055
- const vertex = this.g.addV("Annotation").property("id", id).property("resourceId", targetSource).property("text", targetSelector ? getExactText3(targetSelector) : "").property("selector", JSON.stringify(targetSelector || {})).property("type", bodyType).property("motivation", motivation).property("creator", JSON.stringify(input.creator)).property("created", annotation.created);
2056
- if (bodySource) {
2057
- vertex.property("source", bodySource);
1959
+ let vertex = this.g.addV("Annotation");
1960
+ for (const [key, value] of Object.entries(props)) {
1961
+ vertex = vertex.property(key, value);
2058
1962
  }
2059
1963
  const annVertex = await vertex.next();
2060
1964
  await this.g.V(annVertex.value).addE("BELONGS_TO").to(this.g.V().has("Resource", "id", targetSource)).next();
@@ -2071,7 +1975,7 @@ var JanusGraphDatabase = class {
2071
1975
  }
2072
1976
  await this.g.V(annVertex.value).addE("TAGGED_AS").to(this.g.V(etVertex.value)).next();
2073
1977
  }
2074
- this.logger?.info("Created annotation in JanusGraph", { id });
1978
+ this.logger?.info("Created annotation in JanusGraph", { id: annotation.id });
2075
1979
  return annotation;
2076
1980
  }
2077
1981
  async getAnnotation(id) {
@@ -2081,16 +1985,17 @@ var JanusGraphDatabase = class {
2081
1985
  }
2082
1986
  const entityTypeVertices = await this.g.V().has("Annotation", "id", id).out("TAGGED_AS").has("EntityType").toList();
2083
1987
  const entityTypes = entityTypeVertices.map(
2084
- (v) => this.getPropertyValue(v.properties || {}, "name")
1988
+ (v) => getPropertyValue(v.properties || {}, "name")
2085
1989
  ).filter(Boolean);
2086
- return this.vertexToAnnotation(vertices[0], entityTypes);
1990
+ return vertexToAnnotation2(vertices[0], entityTypes);
2087
1991
  }
2088
1992
  async updateAnnotation(id, updates) {
2089
1993
  const traversalQuery = this.g.V().has("Annotation", "id", id);
2090
1994
  if (updates.target !== void 0 && typeof updates.target !== "string") {
2091
1995
  if (updates.target.selector !== void 0) {
2092
- await traversalQuery.property("text", getExactText3(updates.target.selector)).next();
2093
- await traversalQuery.property("selector", JSON.stringify(updates.target.selector)).next();
1996
+ for (const [key, value] of Object.entries(encodeSelector(updates.target.selector))) {
1997
+ await traversalQuery.property(key, value).next();
1998
+ }
2094
1999
  }
2095
2000
  }
2096
2001
  if (updates.body !== void 0) {
@@ -2138,8 +2043,7 @@ var JanusGraphDatabase = class {
2138
2043
  traversalQuery = traversalQuery.has("resourceId", filter.resourceId);
2139
2044
  }
2140
2045
  if (filter.type) {
2141
- const w3cType = filter.type === "highlight" ? "TextualBody" : "SpecificResource";
2142
- traversalQuery = traversalQuery.has("type", w3cType);
2046
+ traversalQuery = traversalQuery.has("type", storedAnnotationType(motivationForCategory(filter.type)));
2143
2047
  }
2144
2048
  const vertices = await traversalQuery.toList();
2145
2049
  const annotations = await this.fetchAnnotationsWithEntityTypes(vertices);
@@ -2338,8 +2242,8 @@ var JanusGraphDatabase = class {
2338
2242
  let entityTypesFromDb = [];
2339
2243
  for (const vertex of collections) {
2340
2244
  const props = vertex.properties || {};
2341
- const type = this.getPropertyValue(props, "type");
2342
- const tagsJson = this.getPropertyValue(props, "tags");
2245
+ const type = getPropertyValue(props, "type");
2246
+ const tagsJson = getPropertyValue(props, "tags");
2343
2247
  const tags = tagsJson ? JSON.parse(tagsJson) : [];
2344
2248
  if (type === "entity-types") {
2345
2249
  entityTypesFromDb = tags;
@@ -2362,9 +2266,10 @@ var JanusGraphDatabase = class {
2362
2266
  };
2363
2267
 
2364
2268
  // src/implementations/memorygraph.ts
2365
- import { resourceId as makeResourceId2, annotationId as makeAnnotationId4 } from "@semiont/core";
2269
+ import { resourceId as makeResourceId2 } from "@semiont/core";
2366
2270
  import { v4 as uuidv44 } from "uuid";
2367
2271
  import { getBodySource as getBodySource4, getTargetSource as getTargetSource3, getResourceId as getResourceId3, getPrimaryRepresentation as getPrimaryRepresentation4, getResourceEntityTypes as getResourceEntityTypes2 } from "@semiont/core";
2272
+ import { getEntityTypes as getEntityTypes4 } from "@semiont/ontology";
2368
2273
  var MemoryGraphDatabase = class {
2369
2274
  connected = false;
2370
2275
  logger;
@@ -2417,16 +2322,10 @@ var MemoryGraphDatabase = class {
2417
2322
  }
2418
2323
  async createAnnotation(input) {
2419
2324
  const id = input.id;
2420
- const annotation = {
2421
- "@context": "http://www.w3.org/ns/anno.jsonld",
2422
- "type": "Annotation",
2423
- id: makeAnnotationId4(id),
2424
- motivation: input.motivation,
2425
- target: input.target,
2426
- body: input.body,
2427
- creator: input.creator,
2428
- created: (/* @__PURE__ */ new Date()).toISOString()
2429
- };
2325
+ const annotation = decodeAnnotation(
2326
+ encodeAnnotation(buildAnnotation(input, (/* @__PURE__ */ new Date()).toISOString())),
2327
+ getEntityTypes4(input)
2328
+ );
2430
2329
  this.annotations.set(id, annotation);
2431
2330
  this.logger?.debug("Created annotation", {
2432
2331
  id,
@@ -2492,16 +2391,9 @@ var MemoryGraphDatabase = class {
2492
2391
  }
2493
2392
  async getEntityReferences(resourceId, entityTypes) {
2494
2393
  const resourceIdStr = String(resourceId);
2495
- let refs = Array.from(this.annotations.values()).filter((sel) => {
2496
- if (getTargetSource3(sel.target) !== resourceIdStr) return false;
2497
- const bodyEntityTypes = sel.body?.entityTypes;
2498
- return Array.isArray(bodyEntityTypes) && bodyEntityTypes.length > 0;
2499
- });
2394
+ let refs = Array.from(this.annotations.values()).filter((sel) => getTargetSource3(sel.target) === resourceIdStr && getEntityTypes4(sel).length > 0);
2500
2395
  if (entityTypes && entityTypes.length > 0) {
2501
- refs = refs.filter((sel) => {
2502
- const bodyEntityTypes = sel.body?.entityTypes || [];
2503
- return bodyEntityTypes.some((type) => entityTypes.includes(type));
2504
- });
2396
+ refs = refs.filter((sel) => getEntityTypes4(sel).some((type) => entityTypes.includes(type)));
2505
2397
  }
2506
2398
  return refs;
2507
2399
  }
@@ -2591,10 +2483,9 @@ var MemoryGraphDatabase = class {
2591
2483
  const annotations = Array.from(this.annotations.values());
2592
2484
  const highlightCount = annotations.filter((a) => a.motivation === "highlighting").length;
2593
2485
  const referenceCount = annotations.filter((a) => a.motivation === "linking").length;
2594
- const entityReferenceCount = annotations.filter((a) => {
2595
- const bodyEntityTypes = a.body?.entityTypes;
2596
- return a.motivation === "linking" && Array.isArray(bodyEntityTypes) && bodyEntityTypes.length > 0;
2597
- }).length;
2486
+ const entityReferenceCount = annotations.filter(
2487
+ (a) => a.motivation === "linking" && getEntityTypes4(a).length > 0
2488
+ ).length;
2598
2489
  return {
2599
2490
  resourceCount: this.resources.size,
2600
2491
  annotationCount: this.annotations.size,