@semiont/graph 0.5.30 → 0.5.32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/interface.ts","../src/resource-query.ts","../src/implementations/neptune.ts","../src/annotation-codec.ts","../src/implementations/neo4j.ts","../src/implementations/janusgraph.ts","../src/implementations/memorygraph.ts","../src/factory.ts"],"sourcesContent":["// Graph database interface - all implementations must follow this contract\n\nimport type {\n Annotation,\n AnnotationCategory,\n AnnotationId,\n CreateAnnotationInternal,\n EntityTypeStats,\n GraphConnection,\n GraphPath,\n ResourceDescriptor,\n ResourceFilter,\n ResourceId,\n UpdateResourceInput,\n} from '@semiont/core';\n\nconst MUTABLE_RESOURCE_FACETS = new Set<string>(['archived', 'entityTypes']);\n\n/**\n * Resources are immutable apart from two facets: archival state, and entity\n * tags (mutable since the controlled-vocabulary decision — the Weaver folds\n * `mark:archived`/`mark:unarchived` and `mark:entity-tag-added`/`-removed`\n * through `updateResource`). Every implementation validates its input with\n * this one guard so the mutability contract cannot drift per gateway.\n */\nexport function assertMutableResourceUpdate(input: UpdateResourceInput): void {\n const keys = Object.keys(input);\n if (keys.length === 0 || keys.some((k) => !MUTABLE_RESOURCE_FACETS.has(k))) {\n throw new Error('Resources are immutable apart from archival state and entity tags.');\n }\n}\n\n/**\n * Newest first, ties broken by id — the ordering every `listResources` result\n * must carry.\n *\n * The tiebreak is not cosmetic: browse pages these results with offset/limit,\n * and a partial order lets two pages repeat or drop rows. Ids compare by code\n * point rather than locale so the JS gateways agree with the engines, whose\n * `ORDER BY` is codepoint-ordered.\n */\nexport function compareByRecencyThenId(a: ResourceDescriptor, b: ResourceDescriptor): number {\n const aTime = a.dateCreated ? Date.parse(a.dateCreated) : 0;\n const bTime = b.dateCreated ? Date.parse(b.dateCreated) : 0;\n if (aTime !== bTime) return bTime - aTime;\n const aId = String(a['@id']);\n const bId = String(b['@id']);\n return aId < bId ? -1 : aId > bId ? 1 : 0;\n}\n\nexport interface GraphDatabase {\n // Connection management\n connect(): Promise<void>;\n disconnect(): Promise<void>;\n isConnected(): boolean;\n\n // Resource operations\n // Accepts W3C ResourceDescriptor directly - GraphDB stores W3C compliant resources\n createResource(resource: ResourceDescriptor): Promise<ResourceDescriptor>;\n getResource(id: ResourceId): Promise<ResourceDescriptor | null>;\n updateResource(id: ResourceId, input: UpdateResourceInput): Promise<ResourceDescriptor>;\n deleteResource(id: ResourceId): Promise<void>;\n listResources(filter: ResourceFilter): Promise<{ resources: ResourceDescriptor[]; total: number }>;\n\n // Annotation operations\n createAnnotation(input: CreateAnnotationInternal): Promise<Annotation>;\n getAnnotation(id: AnnotationId): Promise<Annotation | null>;\n updateAnnotation(id: AnnotationId, updates: Partial<Annotation>): Promise<Annotation>;\n deleteAnnotation(id: AnnotationId): Promise<void>;\n listAnnotations(filter: { resourceId?: ResourceId; type?: AnnotationCategory }): Promise<{ annotations: Annotation[]; total: number }>;\n\n // Highlight operations\n getHighlights(resourceId: ResourceId): Promise<Annotation[]>;\n\n // Reference operations\n resolveReference(annotationId: AnnotationId, source: ResourceId): Promise<Annotation>;\n getReferences(resourceId: ResourceId): Promise<Annotation[]>;\n getEntityReferences(resourceId: ResourceId, entityTypes?: string[]): Promise<Annotation[]>;\n\n // Relationship queries\n getResourceAnnotations(resourceId: ResourceId): Promise<Annotation[]>;\n getResourceReferencedBy(resourceId: ResourceId, motivation?: string): Promise<Annotation[]>;\n\n // Graph traversal\n getResourceConnections(resourceId: ResourceId): Promise<GraphConnection[]>;\n findPath(fromResourceId: ResourceId, toResourceId: ResourceId, maxDepth?: number): Promise<GraphPath[]>;\n \n // Analytics\n getEntityTypeStats(): Promise<EntityTypeStats[]>;\n getStats(): Promise<{\n resourceCount: number;\n annotationCount: number;\n highlightCount: number;\n referenceCount: number;\n entityReferenceCount: number;\n entityTypes: Record<string, number>;\n contentTypes: Record<string, number>;\n }>;\n \n // Bulk operations\n batchCreateResources(resources: ResourceDescriptor[]): Promise<ResourceDescriptor[]>;\n createAnnotations(inputs: CreateAnnotationInternal[]): Promise<Annotation[]>;\n resolveReferences(inputs: { annotationId: AnnotationId; source: ResourceId }[]): Promise<Annotation[]>;\n\n // Auto-detection\n detectAnnotations(resourceId: ResourceId): Promise<Annotation[]>;\n \n // Tag Collections\n getEntityTypes(): Promise<string[]>;\n addEntityType(tag: string): Promise<void>;\n addEntityTypes(tags: string[]): Promise<void>;\n \n // Utility\n generateId(): string;\n clearDatabase(): Promise<void>; // For testing\n}","/**\n * The resource query — filtering, ranking and pagination — expressed in JS.\n *\n * Shared by every gateway whose engine does not express it directly (memory,\n * JanusGraph, Neptune) so those three cannot drift apart. Neo4j expresses the\n * same semantics in Cypher, and the interface contract tests pin both shapes to\n * one behaviour.\n */\n\nimport { getResourceEntityTypes, getStorageUri } from '@semiont/core';\nimport type { ResourceDescriptor, ResourceFilter } from '@semiont/core';\nimport { compareByRecencyThenId } from './interface';\n\n/**\n * Split a query into the terms every match must satisfy. Blank input yields no\n * terms, which callers read as \"no query\" — a bare substring match on `\" \"`\n * would otherwise match every name containing a space.\n */\nexport function searchTerms(query: string): string[] {\n return query.toLowerCase().split(/\\s+/).filter(Boolean);\n}\n\n/**\n * How directly a resource answers the query: 0 exact name, 1 name prefix,\n * 2 every term present in the name, 3 something other than the name — the path\n * or an entity type — had to supply a term.\n *\n * Those assisted hits rank last deliberately. Someone searching \"Marathon\"\n * wants the document *called* Marathon before every file that merely lives\n * under a folder of that name or is tagged with it.\n */\nexport function searchRank(resource: ResourceDescriptor, query: string): number {\n const whole = query.trim().toLowerCase();\n const name = (resource.name ?? '').toLowerCase();\n if (name === whole) return 0;\n if (name.startsWith(whole)) return 1;\n if (searchTerms(query).every((term) => name.includes(term))) return 2;\n return 3;\n}\n\n/**\n * Every term must appear, though each may come from the name, the path or an\n * entity type — so \"Aeschylus Marathon\" finds a resource named for one and\n * filed under the other, and \"Historian\" finds what is tagged as one.\n */\nfunction matchesSearch(resource: ResourceDescriptor, terms: string[]): boolean {\n const name = (resource.name ?? '').toLowerCase();\n const uri = getStorageUri(resource)?.toLowerCase() ?? '';\n const types = getResourceEntityTypes(resource).map((t) => t.toLowerCase());\n return terms.every((term) =>\n name.includes(term) || uri.includes(term) || types.some((t) => t.includes(term)));\n}\n\n/**\n * Filter, order and page a resource set. Filters always run before pagination,\n * so `total` describes the match set rather than the page.\n */\nexport function queryResources(\n all: ResourceDescriptor[],\n filter: ResourceFilter,\n): { resources: ResourceDescriptor[]; total: number } {\n let matches = all;\n\n if (filter.entityTypes && filter.entityTypes.length > 0) {\n matches = matches.filter((doc) =>\n filter.entityTypes!.some((type) => getResourceEntityTypes(doc).includes(type)));\n }\n\n // A query of only whitespace has no terms, and so filters nothing.\n const terms = filter.search ? searchTerms(filter.search) : [];\n if (terms.length > 0) {\n matches = matches.filter((doc) => matchesSearch(doc, terms));\n }\n\n if (filter.archived !== undefined) {\n matches = matches.filter((doc) => (doc.archived ?? false) === filter.archived);\n }\n\n const search = terms.length > 0 ? filter.search! : undefined;\n const ordered = [...matches].sort(\n search\n ? (a, b) => (searchRank(a, search) - searchRank(b, search)) || compareByRecencyThenId(a, b)\n : compareByRecencyThenId,\n );\n\n const offset = filter.offset ?? 0;\n const limit = filter.limit ?? 20;\n return { resources: ordered.slice(offset, offset + limit), total: ordered.length };\n}\n","// AWS Neptune implementation of GraphDatabase interface\n// Uses Gremlin for graph traversal\n\nimport { GraphDatabase } from '../interface';\nimport { assertMutableResourceUpdate } from '../interface';\nimport { queryResources } from '../resource-query';\nimport { getEntityTypes } from '@semiont/ontology';\nimport type { Logger } from '@semiont/core';\nimport {\n buildAnnotation,\n decodeAnnotation,\n encodeAnnotation,\n encodeSelector,\n motivationForCategory,\n storedAnnotationType,\n type AnnotationProperties,\n} from '../annotation-codec';\nimport type {\n AnnotationCategory,\n GraphConnection,\n GraphPath,\n EntityTypeStats,\n ResourceFilter,\n UpdateResourceInput,\n CreateAnnotationInternal,\n ResourceId,\n AnnotationId,\n} from '@semiont/core';\nimport { v4 as uuidv4 } from 'uuid';\nimport { getBodySource, getTargetSource, getPrimaryRepresentation, getResourceId, getStorageUri } from '@semiont/core';\nimport type { ResourceDescriptor } from '@semiont/core';\nimport type { Annotation } from '@semiont/core';\n\n// Dynamic imports for AWS SDK and Gremlin\nlet NeptuneClient: any;\nlet DescribeDBClustersCommand: any;\nlet gremlin: any;\nlet process: any;\nlet TextP: any;\nlet cardinality: any;\nlet __: any;\n\nasync function loadDependencies() {\n if (!NeptuneClient) {\n const neptuneModule = await import('@aws-sdk/client-neptune');\n NeptuneClient = neptuneModule.NeptuneClient;\n DescribeDBClustersCommand = neptuneModule.DescribeDBClustersCommand;\n }\n if (!gremlin) {\n // @ts-ignore - gremlin module has no types\n gremlin = await import('gremlin');\n process = gremlin.process;\n TextP = process.TextP;\n cardinality = process.cardinality;\n __ = process.statics;\n }\n}\n\n// Helper function to convert Neptune vertex to ResourceDescriptor\nfunction vertexToResource(vertex: any): ResourceDescriptor {\n const props = vertex.properties || vertex;\n\n // Handle different property formats from Neptune\n const getValue = (key: string, required: boolean = false) => {\n const prop = props[key];\n if (!prop) {\n if (required) {\n throw new Error(`Resource ${vertex.id || 'unknown'} missing required field: ${key}`);\n }\n return undefined;\n }\n if (Array.isArray(prop) && prop.length > 0) {\n return prop[0].value !== undefined ? prop[0].value : prop[0];\n }\n return prop.value !== undefined ? prop.value : prop;\n };\n\n // Get all required fields and validate\n const id = getValue('id', true);\n const name = getValue('name', true);\n const entityTypesRaw = getValue('entityTypes', true);\n const mediaType = getValue('mediaType', true);\n const archived = getValue('archived', true);\n const dateCreated = getValue('dateCreated', true);\n const checksum = getValue('checksum', true);\n const creatorRaw = getValue('creator', true);\n\n const resource: ResourceDescriptor = {\n '@context': 'https://schema.org/',\n '@id': id,\n name,\n entityTypes: JSON.parse(entityTypesRaw),\n representations: [{\n mediaType,\n checksum,\n rel: 'original',\n storageUri: getValue('storageUri') || undefined,\n }],\n archived: archived === 'true' || archived === true,\n dateCreated,\n wasAttributedTo: typeof creatorRaw === 'string' ? JSON.parse(creatorRaw) : creatorRaw,\n };\n\n const sourceResourceId = getValue('sourceResourceId');\n if (sourceResourceId) resource.sourceResourceId = sourceResourceId;\n\n return resource;\n}\n\n/**\n * Convert a Neptune vertex to an Annotation.\n *\n * Exported so the cross-store conformance suite can run this store's decode\n * path with no live Neptune: everything past the flattening below is the\n * shared codec's.\n */\nexport function vertexToAnnotation(vertex: any, entityTypes: string[] = []): Annotation {\n return decodeAnnotation(normalizeProperties(vertex.properties || vertex), entityTypes);\n}\n\n/** Neptune returns each property in one of several shapes depending on the traversal. */\nfunction normalizeProperties(props: any): AnnotationProperties {\n const normalized: AnnotationProperties = {};\n for (const [key, raw] of Object.entries(props ?? {})) {\n const value = unwrap(raw);\n if (value === undefined || value === null) continue;\n normalized[key] = typeof value === 'string' ? value : String(value);\n }\n return normalized;\n}\n\nfunction unwrap(prop: any): any {\n if (prop === undefined || prop === null) return undefined;\n if (Array.isArray(prop)) return prop.length > 0 ? unwrap(prop[0]) : undefined;\n if (typeof prop === 'object' && 'value' in prop) return prop.value;\n return prop;\n}\n\n\nexport class NeptuneGraphDatabase implements GraphDatabase {\n private connected: boolean = false;\n private neptuneEndpoint?: string;\n private neptunePort: number = 8182;\n private region?: string;\n private logger?: Logger;\n private g: any; // Gremlin graph traversal source\n private connection: any; // Gremlin connection\n\n // Helper method to fetch annotations with their entity types\n private async fetchAnnotationsWithEntityTypes(annotationVertices: any[]): Promise<Annotation[]> {\n const annotations: Annotation[] = [];\n\n for (const vertex of annotationVertices) {\n const id = vertex.properties?.id?.[0]?.value || vertex.id;\n\n // Fetch entity types for this annotation\n const entityTypesResult = await this.g.V()\n .hasLabel('Annotation')\n .has('id', id)\n .out('TAGGED_AS')\n .hasLabel('EntityType')\n .values('name')\n .toList();\n\n const entityTypes = entityTypesResult || [];\n annotations.push(vertexToAnnotation(vertex, entityTypes));\n }\n\n return annotations;\n }\n\n constructor(config: {\n endpoint?: string;\n port?: number;\n region?: string;\n logger?: Logger;\n } = {}) {\n if (config.endpoint) this.neptuneEndpoint = config.endpoint;\n this.neptunePort = config.port || 8182;\n if (config.region) this.region = config.region;\n this.logger = config.logger;\n }\n \n private async discoverNeptuneEndpoint(): Promise<void> {\n // If endpoint is already provided, use it\n if (this.neptuneEndpoint) {\n return;\n }\n \n // In AWS environment, discover Neptune cluster endpoint\n if (!this.region) {\n throw new Error('AWS region must be configured in environment JSON file (aws.region) for Neptune endpoint discovery');\n }\n\n try {\n // Load AWS SDK dynamically\n await loadDependencies();\n \n // Create Neptune client\n const client = new NeptuneClient({ region: this.region });\n \n // List all Neptune clusters\n const command = new DescribeDBClustersCommand({});\n const response = await client.send(command);\n \n if (!response.DBClusters || response.DBClusters.length === 0) {\n throw new Error('No Neptune clusters found in region ' + this.region);\n }\n \n // Find the Semiont cluster by tags\n let cluster = null;\n for (const dbCluster of response.DBClusters) {\n // Check if this cluster has our application tag\n const tagsCommand = new DescribeDBClustersCommand({\n DBClusterIdentifier: dbCluster.DBClusterIdentifier\n });\n const clusterDetails = await client.send(tagsCommand);\n \n if (clusterDetails.DBClusters && clusterDetails.DBClusters[0]) {\n const clusterInfo = clusterDetails.DBClusters[0];\n // Check for Semiont tag or name pattern\n if (clusterInfo.DBClusterIdentifier?.includes('Semiont') || \n clusterInfo.DBClusterIdentifier?.includes('semiont')) {\n cluster = clusterInfo;\n break;\n }\n }\n }\n \n if (!cluster) {\n throw new Error('No Semiont Neptune cluster found in region ' + this.region);\n }\n \n // Set the endpoint and port\n this.neptuneEndpoint = cluster.Endpoint;\n this.neptunePort = cluster.Port || 8182;\n\n this.logger?.info('Discovered Neptune endpoint', { endpoint: this.neptuneEndpoint, port: this.neptunePort });\n } catch (error: any) {\n this.logger?.error('Failed to discover Neptune endpoint', { error });\n throw error;\n }\n }\n \n async connect(): Promise<void> {\n // Discover Neptune endpoint if needed\n await this.discoverNeptuneEndpoint();\n \n try {\n // Load Gremlin dynamically\n await loadDependencies();\n \n // Create Gremlin connection\n const traversal = gremlin.process.AnonymousTraversalSource.traversal;\n const DriverRemoteConnection = gremlin.driver.DriverRemoteConnection;\n \n // Neptune requires WebSocket Secure (wss) protocol\n const connectionUrl = `wss://${this.neptuneEndpoint}:${this.neptunePort}/gremlin`;\n this.logger?.info('Connecting to Neptune', { connectionUrl });\n\n // Create the connection\n this.connection = new DriverRemoteConnection(connectionUrl, {\n authenticator: null, // Neptune uses IAM authentication via task role\n rejectUnauthorized: true,\n traversalSource: 'g'\n });\n\n // Create the graph traversal source\n this.g = traversal().withRemote(this.connection);\n\n // Test the connection\n const count = await this.g.V().limit(1).count().next();\n this.logger?.info('Connected to Neptune', { vertexCountTest: count.value });\n\n this.connected = true;\n } catch (error: any) {\n this.logger?.error('Failed to connect to Neptune', { error });\n throw error;\n }\n }\n \n async disconnect(): Promise<void> {\n // Close Gremlin connection if it exists\n if (this.connection) {\n try {\n await this.connection.close();\n } catch (error) {\n this.logger?.error('Error closing Neptune connection', { error });\n }\n }\n\n this.connected = false;\n this.logger?.info('Disconnected from Neptune');\n }\n \n isConnected(): boolean {\n return this.connected;\n }\n\n async createResource(resource: ResourceDescriptor): Promise<ResourceDescriptor> {\n const id = getResourceId(resource);\n const primaryRep = getPrimaryRepresentation(resource);\n if (!primaryRep) {\n throw new Error('Resource must have at least one representation');\n }\n\n // Create vertex in Neptune\n try {\n const vertex = this.g.addV('Resource')\n .property('id', id)\n .property('name', resource.name)\n .property('mediaType', primaryRep.mediaType)\n .property('archived', resource.archived || false)\n .property('dateCreated', resource.dateCreated)\n .property('creator', JSON.stringify(resource.wasAttributedTo))\n .property('checksum', primaryRep.checksum)\n .property('entityTypes', JSON.stringify(resource.entityTypes));\n\n if (resource.sourceResourceId) {\n vertex.property('sourceResourceId', resource.sourceResourceId);\n }\n const storageUri = getStorageUri(resource);\n if (storageUri) {\n vertex.property('storageUri', storageUri);\n }\n\n await vertex.next();\n\n this.logger?.info('Created resource vertex in Neptune', { id });\n return resource;\n } catch (error) {\n this.logger?.error('Failed to create resource in Neptune', { error });\n throw error;\n }\n }\n \n async getResource(id: ResourceId): Promise<ResourceDescriptor | null> {\n try {\n const result = await this.g.V()\n .hasLabel('Resource')\n .has('id', id)\n .elementMap()\n .next();\n \n if (!result.value) {\n return null;\n }\n \n return vertexToResource(result.value);\n } catch (error) {\n this.logger?.error('Failed to get resource from Neptune', { error });\n throw error;\n }\n }\n \n async updateResource(id: ResourceId, input: UpdateResourceInput): Promise<ResourceDescriptor> {\n assertMutableResourceUpdate(input);\n\n try {\n let traversal = this.g.V()\n .hasLabel('Resource')\n .has('id', id);\n if (input.archived !== undefined) {\n traversal = traversal.property('archived', input.archived);\n }\n if (input.entityTypes !== undefined) {\n // Mirrors createResource's storage idiom: entityTypes ride as JSON.\n traversal = traversal.property('entityTypes', JSON.stringify(input.entityTypes));\n }\n const result = await traversal\n .elementMap()\n .next();\n\n if (!result.value) {\n throw new Error('Resource not found');\n }\n\n return vertexToResource(result.value);\n } catch (error) {\n this.logger?.error('Failed to update resource in Neptune', { error });\n throw error;\n }\n }\n \n async deleteResource(id: ResourceId): Promise<void> {\n try {\n // Delete the resource vertex and all connected edges\n await this.g.V()\n .hasLabel('Resource')\n .has('id', id)\n .drop()\n .iterate();\n\n this.logger?.info('Deleted resource from Neptune', { id });\n } catch (error) {\n this.logger?.error('Failed to delete resource from Neptune', { error });\n throw error;\n }\n }\n \n /**\n * Filtering, ranking and pagination happen in JS rather than in Gremlin.\n *\n * The ranking ladder (exact name over prefix over substring over path- or\n * tag-assisted) has no natural Gremlin expression, and a rank applied after\n * `range()` would order one page instead of the match set. JanusGraph\n * post-filters for the same reason. Both share `queryResources` with the\n * memory backend so search cannot mean three different things across three\n * gateways.\n *\n * The cost is explicit and accepted: this materializes every `Resource`\n * vertex per call, so it is O(N) in the size of the KB rather than in the\n * size of the result. Neo4j is the production path and pushes the whole\n * query — filter, rank, page — into Cypher; Neptune and JanusGraph are not\n * deployment targets today. If either becomes one at scale, the fix is a\n * Gremlin rank expression (`choose` over `toLower`, engine-version\n * permitting), not a return to per-gateway search semantics.\n */\n async listResources(filter: ResourceFilter): Promise<{ resources: ResourceDescriptor[]; total: number }> {\n try {\n const results = await this.g.V().hasLabel('Resource').elementMap().toList();\n return queryResources(results.map(vertexToResource), filter);\n } catch (error) {\n this.logger?.error('Failed to list resources from Neptune', { error });\n throw error;\n }\n }\n\n \n async createAnnotation(input: CreateAnnotationInternal): Promise<Annotation> {\n // The caller's id is the system of record's — never mint a fresh one\n // (the event-log id is what deletes and lookups arrive under).\n const annotation = buildAnnotation(input, new Date().toISOString());\n const props = encodeAnnotation(annotation);\n const targetSource = props.resourceId!;\n const bodySource = props.source;\n const entityTypes = getEntityTypes(input);\n\n try {\n // Create Annotation vertex — every property comes from the codec, so\n // a source-only target contributes no `selector` property at all.\n let vertex = this.g.addV('Annotation');\n for (const [key, value] of Object.entries(props)) {\n vertex = vertex.property(key, value);\n }\n\n const newVertex = await vertex.next();\n\n // Create edge from Annotation to Resource (BELONGS_TO)\n await this.g.V(newVertex.value)\n .addE('BELONGS_TO')\n .to(this.g.V().hasLabel('Resource').has('id', targetSource)) // Use full URI\n .next();\n\n // If it's a resolved reference, create edge to target resource (REFERENCES)\n if (bodySource) {\n await this.g.V(newVertex.value)\n .addE('REFERENCES')\n .to(this.g.V().hasLabel('Resource').has('id', bodySource)) // Use full URI\n .next();\n }\n\n // Create TAGGED_AS relationships for entity types\n for (const entityType of entityTypes) {\n // Get or create EntityType vertex\n const etVertex = await this.g.V()\n .hasLabel('EntityType')\n .has('name', entityType)\n .fold()\n .coalesce(\n __.unfold(),\n this.g.addV('EntityType').property('name', entityType)\n )\n .next();\n\n // Create TAGGED_AS edge from Annotation to EntityType\n await this.g.V(newVertex.value)\n .addE('TAGGED_AS')\n .to(this.g.V(etVertex.value))\n .next();\n }\n\n this.logger?.info('Created annotation vertex in Neptune', { id: annotation.id });\n return annotation;\n } catch (error) {\n this.logger?.error('Failed to create annotation in Neptune', { error });\n throw error;\n }\n }\n \n async getAnnotation(id: AnnotationId): Promise<Annotation | null> {\n try {\n const result = await this.g.V()\n .hasLabel('Annotation')\n .has('id', id)\n .elementMap()\n .next();\n\n if (!result.value) {\n return null;\n }\n\n // Fetch entity types from TAGGED_AS relationships\n const entityTypesResult = await this.g.V()\n .hasLabel('Annotation')\n .has('id', id)\n .out('TAGGED_AS')\n .hasLabel('EntityType')\n .values('name')\n .toList();\n\n const entityTypes = entityTypesResult || [];\n\n return vertexToAnnotation(result.value, entityTypes);\n } catch (error) {\n this.logger?.error('Failed to get annotation from Neptune', { error });\n throw error;\n }\n }\n \n async updateAnnotation(id: AnnotationId, updates: Partial<Annotation>): Promise<Annotation> {\n try {\n let traversal = this.g.V()\n .hasLabel('Annotation')\n .has('id', id);\n\n // Update target properties\n if (updates.target !== undefined && typeof updates.target !== 'string') {\n if (updates.target.selector !== undefined) {\n for (const [key, value] of Object.entries(encodeSelector(updates.target.selector))) {\n traversal = traversal.property(key, value);\n }\n }\n }\n\n // Update body properties and entity types\n if (updates.body !== undefined) {\n const bodySource = getBodySource(updates.body);\n const entityTypes = getEntityTypes({ body: updates.body });\n\n if (bodySource) {\n traversal = traversal.property('source', bodySource);\n }\n\n // Update entity type relationships - remove old ones and create new ones\n if (entityTypes.length >= 0) {\n // Remove existing TAGGED_AS edges\n await this.g.V()\n .hasLabel('Annotation')\n .has('id', id)\n .outE('TAGGED_AS')\n .drop()\n .iterate();\n\n // Create new TAGGED_AS edges\n for (const entityType of entityTypes) {\n const etVertex = await this.g.V()\n .hasLabel('EntityType')\n .has('name', entityType)\n .fold()\n .coalesce(\n __.unfold(),\n this.g.addV('EntityType').property('name', entityType)\n )\n .next();\n\n await this.g.V()\n .hasLabel('Annotation')\n .has('id', id)\n .addE('TAGGED_AS')\n .to(this.g.V(etVertex.value))\n .next();\n }\n }\n }\n\n if (updates.modified !== undefined) {\n traversal = traversal.property('modified', updates.modified);\n }\n if (updates.generator !== undefined) {\n traversal = traversal.property('generator', JSON.stringify(updates.generator));\n }\n\n const result = await traversal.elementMap().next();\n\n if (!result.value) {\n throw new Error('Annotation not found');\n }\n\n // Fetch entity types from TAGGED_AS relationships\n const entityTypesResult = await this.g.V()\n .hasLabel('Annotation')\n .has('id', id)\n .out('TAGGED_AS')\n .hasLabel('EntityType')\n .values('name')\n .toList();\n\n const entityTypes = entityTypesResult || [];\n\n return vertexToAnnotation(result.value, entityTypes);\n } catch (error) {\n this.logger?.error('Failed to update annotation in Neptune', { error });\n throw error;\n }\n }\n \n async deleteAnnotation(id: AnnotationId): Promise<void> {\n try {\n await this.g.V()\n .hasLabel('Annotation')\n .has('id', id)\n .drop()\n .iterate();\n\n this.logger?.info('Deleted annotation from Neptune', { id });\n } catch (error) {\n this.logger?.error('Failed to delete annotation from Neptune', { error });\n throw error;\n }\n }\n \n async listAnnotations(filter: { resourceId?: ResourceId; type?: AnnotationCategory }): Promise<{ annotations: Annotation[]; total: number }> {\n try {\n let traversal = this.g.V().hasLabel('Annotation');\n\n // Apply filters\n if (filter.resourceId) {\n traversal = traversal.has('resourceId', filter.resourceId);\n }\n\n if (filter.type) {\n traversal = traversal.has('type', storedAnnotationType(motivationForCategory(filter.type)));\n }\n\n const results = await traversal.elementMap().toList();\n const annotations = await this.fetchAnnotationsWithEntityTypes(results);\n\n return { annotations, total: annotations.length };\n } catch (error) {\n this.logger?.error('Failed to list annotations from Neptune', { error });\n throw error;\n }\n }\n \n \n async getHighlights(resourceId: ResourceId): Promise<Annotation[]> {\n try {\n const results = await this.g.V()\n .hasLabel('Annotation')\n .has('resourceId', resourceId)\n .hasNot('resolvedResourceId')\n .elementMap()\n .toList();\n\n return await this.fetchAnnotationsWithEntityTypes(results);\n } catch (error) {\n this.logger?.error('Failed to get highlights from Neptune', { error });\n throw error;\n }\n }\n \n async resolveReference(annotationId: AnnotationId, source: ResourceId): Promise<Annotation> {\n try {\n // Get target resource name\n const targetDocResult = await this.g.V()\n .hasLabel('Resource')\n .has('id', source)\n .elementMap()\n .next();\n const targetDoc = targetDocResult.value ? vertexToResource(targetDocResult.value) : null;\n\n // Update the existing Annotation vertex\n const traversal = this.g.V()\n .hasLabel('Annotation')\n .has('id', annotationId)\n .property('source', source)\n .property('resolvedResourceName', targetDoc?.name)\n .property('resolvedAt', new Date().toISOString());\n\n const result = await traversal.elementMap().next();\n\n if (!result.value) {\n throw new Error('Annotation not found');\n }\n\n // Create REFERENCES edge to the resolved resource\n const annVertex = await this.g.V()\n .hasLabel('Annotation')\n .has('id', annotationId)\n .next();\n\n await this.g.V(annVertex.value)\n .addE('REFERENCES')\n .to(this.g.V().hasLabel('Resource').has('id', source))\n .next();\n\n // Fetch entity types from TAGGED_AS relationships\n const entityTypesResult = await this.g.V()\n .hasLabel('Annotation')\n .has('id', annotationId)\n .out('TAGGED_AS')\n .hasLabel('EntityType')\n .values('name')\n .toList();\n\n const entityTypes = entityTypesResult || [];\n\n return vertexToAnnotation(result.value, entityTypes);\n } catch (error) {\n this.logger?.error('Failed to resolve reference in Neptune', { error });\n throw error;\n }\n }\n \n async getReferences(resourceId: ResourceId): Promise<Annotation[]> {\n try {\n const results = await this.g.V()\n .hasLabel('Annotation')\n .has('resourceId', resourceId)\n .has('resolvedResourceId')\n .elementMap()\n .toList();\n\n return await this.fetchAnnotationsWithEntityTypes(results);\n } catch (error) {\n this.logger?.error('Failed to get references from Neptune', { error });\n throw error;\n }\n }\n \n async getEntityReferences(resourceId: ResourceId, entityTypes?: string[]): Promise<Annotation[]> {\n try {\n let traversal = this.g.V()\n .hasLabel('Annotation')\n .has('resourceId', resourceId)\n .has('resolvedResourceId')\n .has('entityTypes');\n \n if (entityTypes && entityTypes.length > 0) {\n traversal = traversal.filter(\n process.statics.or(\n ...entityTypes.map((type: string) =>\n process.statics.has('entityTypes', TextP.containing(`\"${type}\"`))\n )\n )\n );\n }\n \n const results = await traversal.elementMap().toList();\n\n return await this.fetchAnnotationsWithEntityTypes(results);\n } catch (error) {\n this.logger?.error('Failed to get entity references from Neptune', { error });\n throw error;\n }\n }\n \n async getResourceAnnotations(resourceId: ResourceId): Promise<Annotation[]> {\n try {\n const results = await this.g.V()\n .hasLabel('Annotation')\n .has('resourceId', resourceId)\n .elementMap()\n .toList();\n\n return await this.fetchAnnotationsWithEntityTypes(results);\n } catch (error) {\n this.logger?.error('Failed to get resource annotations from Neptune', { error });\n throw error;\n }\n }\n \n async getResourceReferencedBy(resourceId: ResourceId, _motivation?: string): Promise<Annotation[]> {\n try {\n const results = await this.g.V()\n .hasLabel('Annotation')\n .has('resolvedResourceId', resourceId)\n .elementMap()\n .toList();\n\n return await this.fetchAnnotationsWithEntityTypes(results);\n } catch (error) {\n this.logger?.error('Failed to get resource referenced by from Neptune', { error });\n throw error;\n }\n }\n \n async getResourceConnections(resourceId: ResourceId): Promise<GraphConnection[]> {\n try {\n // Get all annotations from this resource that reference other resources\n const outgoingAnnotations = await this.g.V()\n .hasLabel('Annotation')\n .has('resourceId', resourceId)\n .has('source')\n .elementMap()\n .toList();\n\n // Get all annotations that reference this resource\n const incomingAnnotations = await this.g.V()\n .hasLabel('Annotation')\n .has('source', resourceId)\n .elementMap()\n .toList();\n\n // Build connections map\n const connectionsMap = new Map<string, GraphConnection>();\n\n // Process outgoing references\n for (const annVertex of outgoingAnnotations) {\n const id = annVertex.properties?.id?.[0]?.value || annVertex.id;\n\n // Fetch entity types for this annotation\n const entityTypesResult = await this.g.V()\n .hasLabel('Annotation')\n .has('id', id)\n .out('TAGGED_AS')\n .hasLabel('EntityType')\n .values('name')\n .toList();\n\n const entityTypes = entityTypesResult || [];\n const annotation = vertexToAnnotation(annVertex, entityTypes);\n const targetDocId = getBodySource(annotation.body);\n if (!targetDocId) continue; // Skip stubs\n\n // Get the target resource\n const targetDocResult = await this.g.V()\n .hasLabel('Resource')\n .has('id', targetDocId)\n .elementMap()\n .next();\n\n if (targetDocResult.value) {\n const targetDoc = vertexToResource(targetDocResult.value);\n const targetDocId = getResourceId(targetDoc);\n if (!targetDocId) continue;\n const existing = connectionsMap.get(targetDocId);\n if (existing) {\n existing.annotations.push(annotation);\n } else {\n connectionsMap.set(targetDocId, {\n targetResource: targetDoc,\n annotations: [annotation],\n bidirectional: false,\n });\n }\n }\n }\n\n // Check for bidirectional connections\n for (const annVertex of incomingAnnotations) {\n const id = annVertex.properties?.id?.[0]?.value || annVertex.id;\n\n // Fetch entity types for this annotation\n const entityTypesResult = await this.g.V()\n .hasLabel('Annotation')\n .has('id', id)\n .out('TAGGED_AS')\n .hasLabel('EntityType')\n .values('name')\n .toList();\n\n const entityTypes = entityTypesResult || [];\n const annotation = vertexToAnnotation(annVertex, entityTypes);\n const sourceDocId = getTargetSource(annotation.target);\n const existing = connectionsMap.get(sourceDocId);\n if (existing) {\n existing.bidirectional = true;\n }\n }\n\n return Array.from(connectionsMap.values());\n } catch (error) {\n this.logger?.error('Failed to get resource connections from Neptune', { error });\n throw error;\n }\n }\n \n async findPath(fromResourceId: string, toResourceId: string, maxDepth: number = 5): Promise<GraphPath[]> {\n try {\n // Use Neptune's optimized path queries\n const results = await this.g.V()\n .hasLabel('Resource')\n .has('id', fromResourceId)\n .repeat(\n process.statics.both('REFERENCES')\n .simplePath()\n )\n .times(maxDepth)\n .emit()\n .has('id', toResourceId)\n .path()\n .by(process.statics.elementMap())\n .limit(10)\n .toList();\n \n const paths: GraphPath[] = [];\n \n for (const pathResult of results) {\n const resources: ResourceDescriptor[] = [];\n\n // Process path elements (alternating vertices and edges)\n for (let i = 0; i < pathResult.objects.length; i++) {\n const element = pathResult.objects[i];\n\n if (i % 2 === 0) {\n // Vertex (Resource)\n resources.push(vertexToResource(element));\n } else {\n // Edge - skip for now as we're using vertex-based annotations\n // We'd need to query for annotations between resources\n }\n }\n\n paths.push({ resources, annotations: [] });\n }\n \n return paths;\n } catch (error) {\n this.logger?.error('Failed to find paths in Neptune', { error });\n throw error;\n }\n }\n \n async getEntityTypeStats(): Promise<EntityTypeStats[]> {\n try {\n // Use Neptune's analytics capabilities\n const results = await this.g.V()\n .hasLabel('Resource')\n .values('entityTypes')\n .map((entityTypesJson: string) => {\n const types = JSON.parse(entityTypesJson);\n return types;\n })\n .unfold()\n .groupCount()\n .next();\n \n const stats: EntityTypeStats[] = [];\n \n if (results.value) {\n for (const [type, count] of Object.entries(results.value)) {\n stats.push({\n type,\n count: count as number,\n });\n }\n }\n \n return stats;\n } catch (error) {\n this.logger?.error('Failed to get entity type stats from Neptune', { error });\n throw error;\n }\n }\n \n async getStats(): Promise<{\n resourceCount: number;\n annotationCount: number;\n highlightCount: number;\n referenceCount: number;\n entityReferenceCount: number;\n entityTypes: Record<string, number>;\n contentTypes: Record<string, number>;\n }> {\n try {\n // Get resource count\n const docCountResult = await this.g.V()\n .hasLabel('Resource')\n .count()\n .next();\n const resourceCount = docCountResult.value || 0;\n \n // Get annotation count\n const selCountResult = await this.g.V()\n .hasLabel('Annotation')\n .count()\n .next();\n const annotationCount = selCountResult.value || 0;\n\n // Get highlight count (annotations without resolved resource)\n const highlightCountResult = await this.g.V()\n .hasLabel('Annotation')\n .hasNot('resolvedResourceId')\n .count()\n .next();\n const highlightCount = highlightCountResult.value || 0;\n\n // Get reference count (annotations with resolved resource)\n const referenceCountResult = await this.g.V()\n .hasLabel('Annotation')\n .has('resolvedResourceId')\n .count()\n .next();\n const referenceCount = referenceCountResult.value || 0;\n\n // Get entity reference count\n const entityRefCountResult = await this.g.V()\n .hasLabel('Annotation')\n .has('resolvedResourceId')\n .has('entityTypes')\n .count()\n .next();\n const entityReferenceCount = entityRefCountResult.value || 0;\n \n // Get entity type stats\n const entityTypeStats = await this.getEntityTypeStats();\n const entityTypes: Record<string, number> = {};\n for (const stat of entityTypeStats) {\n entityTypes[stat.type] = stat.count;\n }\n \n // Get content type stats\n const contentTypeResult = await this.g.V()\n .hasLabel('Resource')\n .groupCount()\n .by('contentType')\n .next();\n const contentTypes = contentTypeResult.value || {};\n \n return {\n resourceCount,\n annotationCount,\n highlightCount,\n referenceCount,\n entityReferenceCount,\n entityTypes,\n contentTypes,\n };\n } catch (error) {\n this.logger?.error('Failed to get stats from Neptune', { error });\n throw error;\n }\n }\n \n async batchCreateResources(resources: ResourceDescriptor[]): Promise<ResourceDescriptor[]> {\n const results: ResourceDescriptor[] = [];\n for (const resource of resources) {\n results.push(await this.createResource(resource));\n }\n return results;\n }\n\n async createAnnotations(inputs: CreateAnnotationInternal[]): Promise<Annotation[]> {\n const results: Annotation[] = [];\n\n try {\n for (const input of inputs) {\n const annotation = await this.createAnnotation(input);\n results.push(annotation);\n }\n\n return results;\n } catch (error) {\n this.logger?.error('Failed to create annotations in Neptune', { error });\n throw error;\n }\n }\n\n\n async resolveReferences(inputs: { annotationId: AnnotationId; source: ResourceId }[]): Promise<Annotation[]> {\n const results: Annotation[] = [];\n\n try {\n for (const input of inputs) {\n const annotation = await this.resolveReference(input.annotationId, input.source);\n results.push(annotation);\n }\n\n return results;\n } catch (error) {\n this.logger?.error('Failed to resolve references in Neptune', { error });\n throw error;\n }\n }\n \n async detectAnnotations(_resourceId: ResourceId): Promise<Annotation[]> {\n // This would use AI/ML to detect annotations in a resource\n // For now, return empty array as a placeholder\n return [];\n }\n \n // Tag Collections - stored as special vertices in the graph\n private entityTypesCollection: Set<string> | null = null;\n \n async getEntityTypes(): Promise<string[]> {\n // Initialize if not already loaded\n if (this.entityTypesCollection === null) {\n await this.initializeTagCollections();\n }\n return Array.from(this.entityTypesCollection!).sort();\n }\n \n async addEntityType(tag: string): Promise<void> {\n if (this.entityTypesCollection === null) {\n await this.initializeTagCollections();\n }\n this.entityTypesCollection!.add(tag);\n // Persist to Neptune\n try {\n await this.g.V()\n .has('tagCollection', 'type', 'entity-types')\n .fold()\n .coalesce(\n __.unfold(),\n __.addV('TagCollection').property('type', 'entity-types')\n )\n .property(cardinality.set, 'tags', tag)\n .iterate();\n } catch (error) {\n this.logger?.error('Failed to add entity type', { error });\n }\n }\n \n async addEntityTypes(tags: string[]): Promise<void> {\n if (this.entityTypesCollection === null) {\n await this.initializeTagCollections();\n }\n tags.forEach(tag => this.entityTypesCollection!.add(tag));\n // Persist to Neptune\n try {\n const vertex = await this.g.V()\n .has('tagCollection', 'type', 'entity-types')\n .fold()\n .coalesce(\n __.unfold(),\n __.addV('TagCollection').property('type', 'entity-types')\n );\n \n for (const tag of tags) {\n await vertex.property(cardinality.set, 'tags', tag).iterate();\n }\n } catch (error) {\n this.logger?.error('Failed to add entity types', { error });\n }\n }\n \n private async initializeTagCollections(): Promise<void> {\n try {\n // Check Neptune for existing collections\n const collections = await this.g.V()\n .hasLabel('TagCollection')\n .project('type', 'tags')\n .by('type')\n .by(__.values('tags').fold())\n .toList();\n\n // Process existing collections\n for (const col of collections) {\n if (col.type === 'entity-types') {\n this.entityTypesCollection = new Set(col.tags as string[]);\n }\n }\n } catch (error) {\n this.logger?.debug('No existing tag collections found, will initialize with defaults');\n }\n\n // Initialize with defaults if not present\n if (this.entityTypesCollection === null) {\n const { DEFAULT_ENTITY_TYPES } = await import('@semiont/ontology');\n this.entityTypesCollection = new Set(DEFAULT_ENTITY_TYPES);\n // Persist defaults to Neptune\n try {\n const vertex = await this.g.addV('TagCollection')\n .property('type', 'entity-types')\n .next();\n for (const tag of DEFAULT_ENTITY_TYPES) {\n await this.g.V(vertex.value.id)\n .property(cardinality.set, 'tags', tag)\n .iterate();\n }\n } catch (error) {\n this.logger?.error('Failed to initialize entity types', { error });\n }\n }\n }\n \n generateId(): string {\n return uuidv4().replace(/-/g, '').substring(0, 12);\n }\n \n async clearDatabase(): Promise<void> {\n try {\n // CAREFUL! This clears the entire graph\n await this.g.V().drop().iterate();\n this.logger?.info('Cleared all data from Neptune');\n // Reset tag collections\n this.entityTypesCollection = null;\n } catch (error) {\n this.logger?.error('Failed to clear Neptune database', { error });\n throw error;\n }\n }\n}","/**\n * The annotation codec — the one module that decides how a W3C annotation\n * becomes stored properties and back.\n *\n * Every store keeps its own dialect (Cypher parameters, Gremlin\n * `.property()` chains, a Map) and its own way of flattening what the driver\n * hands back into a property bag. What none of them owns any more is the\n * SHAPE: the W3C envelope, which fields are required, how a selector is\n * serialized, how the body array is reconstructed from entity tags and a\n * linking source. Those lived in three near-verbatim copies that disagreed\n * in four places, and each disagreement was a bug — a resource-level\n * annotation came back carrying `selector: {}`, which is not a legal\n * selector, and a motivation-less row was silently relabelled `'linking'`.\n *\n * The codec manufactures nothing. Absence is stored as absence and read back\n * as absence, in both directions.\n */\n\nimport { annotationId as makeAnnotationId } from '@semiont/core';\nimport { getBodySource, getExactText, getTargetSelector, getTargetSource } from '@semiont/core';\nimport type { Annotation, AnnotationCategory, CreateAnnotationInternal } from '@semiont/core';\n\n/**\n * A store's property bag, flattened. Producing this is the store's job (D3):\n * neo4j unwraps `node.properties` and its native temporals, the Gremlin\n * stores unwrap `[{value}]` lists. What the values MEAN is the codec's.\n */\nexport type AnnotationProperties = Record<string, string | undefined>;\n\ntype AnnotationTarget = Exclude<Annotation['target'], string>;\ntype AnnotationSelector = NonNullable<AnnotationTarget['selector']>;\ntype AnnotationBody = NonNullable<Annotation['body']>;\n\n/**\n * The stored `type` property, which the category filters match on. It\n * restates the motivation, so it is derived from it here and nowhere else —\n * the three filters that used to hand-write the same mapping had drifted\n * into asking for a value no store ever wrote.\n */\nexport function storedAnnotationType(motivation: Annotation['motivation']): string {\n return motivation === 'highlighting' ? 'TextualBody' : 'SpecificResource';\n}\n\n/** The category a caller filters by, in the vocabulary the annotation stores. */\nexport function motivationForCategory(category: AnnotationCategory): Annotation['motivation'] {\n return category === 'highlight' ? 'highlighting' : 'linking';\n}\n\n/**\n * Mint the annotation a create request describes.\n *\n * `created` is a parameter rather than a `new Date()` here so the codec stays\n * pure — and so it is visible at each call site that the graph stamps its own\n * write time. `CreateAnnotationInternal` carries no timestamp, so the event's\n * own time does not reach this projection at all.\n */\nexport function buildAnnotation(input: CreateAnnotationInternal, created: string): Annotation {\n const annotation: Annotation = {\n '@context': 'http://www.w3.org/ns/anno.jsonld',\n type: 'Annotation',\n id: makeAnnotationId(input.id),\n motivation: input.motivation,\n target: input.target,\n creator: input.creator,\n created,\n };\n if (input.body && (!Array.isArray(input.body) || input.body.length > 0)) {\n annotation.body = input.body;\n }\n return annotation;\n}\n\n/**\n * The annotation's stored properties. Entity tags are not among them — those\n * are edges, and the store writes them from `getEntityTypes(annotation)`.\n */\nexport function encodeAnnotation(annotation: Annotation): Record<string, string> {\n const selector = getTargetSelector(annotation.target);\n const bodySource = getBodySource(annotation.body);\n\n // `created` is optional on the wire but not in the store: a row without it\n // cannot be read back, so refuse to write one rather than mint a timestamp.\n const resourceId = getTargetSource(annotation.target);\n if (!resourceId) throw new Error(`Annotation ${annotation.id} has no target source`);\n if (!annotation.created) throw new Error(`Annotation ${annotation.id} has no created timestamp`);\n\n const props: Record<string, string> = {\n id: annotation.id,\n resourceId,\n type: storedAnnotationType(annotation.motivation),\n motivation: annotation.motivation,\n creator: JSON.stringify(annotation.creator),\n created: annotation.created,\n };\n\n if (selector) Object.assign(props, encodeSelector(selector));\n if (bodySource) props.source = bodySource;\n if (annotation.modified) props.modified = annotation.modified;\n if (annotation.generator) props.generator = JSON.stringify(annotation.generator);\n\n return props;\n}\n\n/**\n * The properties a selector contributes: its serialization, plus the quoted\n * text pulled out beside it. Targeted selector updates go through here too,\n * so no store decides on its own what a selector is called on disk.\n */\nexport function encodeSelector(selector: AnnotationSelector): Record<string, string> {\n const props: Record<string, string> = { selector: JSON.stringify(selector) };\n const exact = getExactText(selector);\n if (exact) props.exact = exact;\n return props;\n}\n\n/**\n * Rebuild the annotation from stored properties and the entity-tag edges the\n * store resolved separately.\n *\n * A field the properties do not carry is omitted, never invented: a\n * source-only target (legal since RESOURCE-LEVEL-ANCHOR) comes back with no\n * `selector`, and a row missing a required field fails loudly by name rather\n * than acquiring a default.\n */\nexport function decodeAnnotation(props: AnnotationProperties, entityTypes: string[] = []): Annotation {\n const id = props.id;\n if (!id) throw new Error('Annotation missing required field: id');\n\n const required = (key: string): string => {\n const value = props[key];\n if (!value) throw new Error(`Annotation ${id} missing required field: ${key}`);\n return value;\n };\n\n const resourceId = required('resourceId');\n const creator = JSON.parse(required('creator'));\n // The stored value is one of the wire vocabulary's, which the event that\n // produced it was validated against; the projection does not re-police it.\n const motivation = required('motivation') as Annotation['motivation'];\n const created = required('created');\n\n const body: AnnotationBody = [];\n for (const entityType of entityTypes) {\n if (entityType) body.push({ type: 'TextualBody', value: entityType, purpose: 'tagging' });\n }\n if (props.source) {\n body.push({ type: 'SpecificResource', source: props.source, purpose: 'linking' });\n }\n\n const selector = decodeSelector(props.selector);\n const target: AnnotationTarget = selector ? { source: resourceId, selector } : { source: resourceId };\n\n const annotation: Annotation = {\n '@context': 'http://www.w3.org/ns/anno.jsonld',\n type: 'Annotation',\n id: makeAnnotationId(id),\n motivation,\n target,\n creator,\n created,\n };\n\n if (body.length > 0) annotation.body = body;\n if (props.modified) annotation.modified = props.modified;\n if (props.generator) {\n try {\n annotation.generator = JSON.parse(props.generator);\n } catch {\n // A corrupt generator is not worth failing the whole read over — the\n // annotation itself is intact, and provenance is advisory.\n }\n }\n\n return annotation;\n}\n\n/**\n * Rows written before RESOURCE-LEVEL-ANCHOR reached the stores hold `'{}'`\n * where a resource-level annotation has no selector at all. `{}` satisfies no\n * branch of the selector union, so it fails validation on the first round\n * trip through a validated channel — reading it back as absent is what makes\n * those rows harmless without a migration.\n */\nfunction decodeSelector(raw: string | undefined): AnnotationSelector | undefined {\n if (!raw) return undefined;\n const parsed = JSON.parse(raw);\n if (!parsed || Object.keys(parsed).length === 0) return undefined;\n return parsed;\n}\n","// Neo4j implementation of GraphDatabase interface\n// Uses Cypher query language\n\nimport type { Driver, Session } from 'neo4j-driver';\nimport { GraphDatabase } from '../interface';\nimport { assertMutableResourceUpdate } from '../interface';\nimport { searchTerms } from '../resource-query';\nimport type { Logger } from '@semiont/core';\nimport type {\n AnnotationCategory,\n GraphConnection,\n GraphPath,\n EntityTypeStats,\n ResourceFilter,\n UpdateResourceInput,\n CreateAnnotationInternal,\n ResourceId,\n AnnotationId,\n} from '@semiont/core';\nimport { v4 as uuidv4 } from 'uuid';\nimport { getPrimaryRepresentation, getStorageUri } from '@semiont/core';\nimport { getEntityTypes } from '@semiont/ontology';\nimport {\n buildAnnotation,\n decodeAnnotation,\n encodeAnnotation,\n motivationForCategory,\n storedAnnotationType,\n type AnnotationProperties,\n} from '../annotation-codec';\n\nimport type { ResourceDescriptor } from '@semiont/core';\nimport type { Annotation } from '@semiont/core';\n\n/**\n * Convert motivation to a valid Neo4j label name\n *\n * Annotations get both a property (`motivation: \"linking\"`) and a label (`:Linking`)\n * for the same motivation value. This enables:\n * - Fast filtering: `MATCH (a:Annotation:Linking)` vs `MATCH (a:Annotation) WHERE a.motivation = 'linking'`\n * - Automatic indexing: Neo4j indexes labels by default\n * - Visual exploration: Graph visualization tools prominently display labels\n *\n * Example: \"linking\" -> \"Linking\", \"commenting\" -> \"Commenting\"\n *\n * W3C Motivation values:\n * assessing, bookmarking, classifying, commenting, describing, editing,\n * highlighting, identifying, linking, moderating, questioning, replying, tagging\n */\nfunction motivationToLabel(motivation: string): string {\n return motivation.charAt(0).toUpperCase() + motivation.slice(1);\n}\n\nexport class Neo4jGraphDatabase implements GraphDatabase {\n private driver: Driver | null = null;\n private neo4j!: typeof import('neo4j-driver');\n private connected: boolean = false;\n private logger?: Logger;\n private config: {\n uri?: string;\n username?: string;\n password?: string;\n database?: string;\n };\n\n // Tag Collections - cached in memory for performance\n private entityTypesCollection: Set<string> | null = null;\n\n constructor(config: {\n uri?: string;\n username?: string;\n password?: string;\n database?: string;\n logger?: Logger;\n } = {}) {\n this.config = config;\n this.logger = config.logger;\n }\n\n async connect(): Promise<void> {\n try {\n const uri = this.config.uri;\n const username = this.config.username;\n const password = this.config.password;\n const database = this.config.database;\n\n if (!uri) {\n throw new Error('Neo4j URI not configured! Pass uri in config.');\n }\n if (!username) {\n throw new Error('Neo4j username not configured! Pass username in config.');\n }\n if (!password) {\n throw new Error('Neo4j password not configured! Pass password in config.');\n }\n if (!database) {\n throw new Error('Neo4j database not configured! Pass database in config.');\n }\n\n this.logger?.info('Connecting to Neo4j', { uri });\n\n this.neo4j = await import('neo4j-driver');\n this.driver = this.neo4j.driver(\n uri,\n this.neo4j.auth.basic(username, password),\n {\n maxConnectionPoolSize: 50,\n connectionAcquisitionTimeout: 60000,\n }\n );\n\n // Test connection\n const session = this.driver.session({ database });\n\n await session.run('RETURN 1 as test');\n await session.close();\n\n // Create constraints and indexes if they don't exist\n await this.ensureSchemaExists();\n\n this.logger?.info('Successfully connected to Neo4j');\n this.connected = true;\n } catch (error) {\n this.logger?.error('Failed to connect to Neo4j', { error });\n throw new Error(`Neo4j connection failed: ${error}`);\n }\n }\n\n async disconnect(): Promise<void> {\n if (this.driver) {\n await this.driver.close();\n this.driver = null;\n }\n this.connected = false;\n }\n\n isConnected(): boolean {\n return this.connected;\n }\n\n private getSession(): Session {\n if (!this.driver) {\n throw new Error('Neo4j driver not initialized');\n }\n if (!this.config.database) {\n throw new Error('Neo4j database not configured! Pass database in config.');\n }\n return this.driver.session({\n database: this.config.database\n });\n }\n\n private async ensureSchemaExists(): Promise<void> {\n const session = this.getSession();\n try {\n // Create constraints for unique IDs\n const constraints = [\n 'CREATE CONSTRAINT doc_id IF NOT EXISTS FOR (d:Resource) REQUIRE d.id IS UNIQUE',\n 'CREATE CONSTRAINT sel_id IF NOT EXISTS FOR (s:Annotation) REQUIRE s.id IS UNIQUE',\n 'CREATE CONSTRAINT tag_id IF NOT EXISTS FOR (t:TagCollection) REQUIRE t.type IS UNIQUE'\n ];\n\n for (const constraint of constraints) {\n try {\n await session.run(constraint);\n } catch (error: any) {\n // Ignore if constraint already exists\n if (!error.message?.includes('already exists')) {\n this.logger?.warn('Schema creation warning', { message: error.message });\n }\n }\n }\n\n // Create indexes for common queries\n const indexes = [\n 'CREATE INDEX doc_name IF NOT EXISTS FOR (d:Resource) ON (d.name)',\n 'CREATE INDEX doc_entity_types IF NOT EXISTS FOR (d:Resource) ON (d.entityTypes)',\n 'CREATE INDEX sel_doc_id IF NOT EXISTS FOR (s:Annotation) ON (s.resourceId)',\n 'CREATE INDEX sel_resolved_id IF NOT EXISTS FOR (s:Annotation) ON (s.resolvedResourceId)'\n ];\n\n for (const index of indexes) {\n try {\n await session.run(index);\n } catch (error: any) {\n // Ignore if index already exists\n if (!error.message?.includes('already exists')) {\n this.logger?.warn('Index creation warning', { message: error.message });\n }\n }\n }\n } finally {\n await session.close();\n }\n }\n\n async createResource(resource: ResourceDescriptor): Promise<ResourceDescriptor> {\n const session = this.getSession();\n try {\n const id = resource['@id']; // Use full URI for consistency\n const primaryRep = getPrimaryRepresentation(resource);\n if (!primaryRep) {\n throw new Error('Resource must have at least one representation');\n }\n\n // Use MERGE instead of CREATE for idempotence and to enrich stub nodes\n // Stub nodes may be created by REFERENCES edge creation before resource.created event\n const result = await session.run(\n `MERGE (d:Resource {id: $id})\n SET d.name = $name,\n d.entityTypes = $entityTypes,\n d.format = $format,\n d.archived = $archived,\n d.created = datetime($created),\n d.creator = $creator,\n d.contentChecksum = $contentChecksum,\n d.sourceAnnotationId = $sourceAnnotationId,\n d.sourceResourceId = $sourceResourceId,\n d.storageUri = $storageUri,\n d.stub = false\n RETURN d`,\n {\n id,\n name: resource.name,\n entityTypes: resource.entityTypes,\n format: primaryRep.mediaType,\n archived: resource.archived || false,\n created: resource.dateCreated,\n creator: JSON.stringify(resource.wasAttributedTo),\n contentChecksum: primaryRep.checksum,\n sourceAnnotationId: resource.sourceAnnotationId ?? null,\n sourceResourceId: resource.sourceResourceId ?? null,\n storageUri: getStorageUri(resource) ?? null,\n }\n );\n\n this.logger?.info('Resource created/enriched', { id });\n return this.parseResourceNode(result.records[0]!.get('d'));\n } finally {\n await session.close();\n }\n }\n\n async getResource(id: ResourceId): Promise<ResourceDescriptor | null> {\n const session = this.getSession();\n try {\n const result = await session.run(\n 'MATCH (d:Resource {id: $id}) RETURN d',\n { id }\n );\n\n if (result.records.length === 0) return null;\n return this.parseResourceNode(result.records[0]!.get('d'));\n } finally {\n await session.close();\n }\n }\n\n async updateResource(id: ResourceId, input: UpdateResourceInput): Promise<ResourceDescriptor> {\n assertMutableResourceUpdate(input);\n\n const sets: string[] = [];\n const params: Record<string, unknown> = { id };\n if (input.archived !== undefined) {\n sets.push('d.archived = $archived');\n params.archived = input.archived;\n }\n if (input.entityTypes !== undefined) {\n sets.push('d.entityTypes = $entityTypes');\n params.entityTypes = input.entityTypes;\n }\n\n const session = this.getSession();\n try {\n const result = await session.run(\n `MATCH (d:Resource {id: $id})\n SET ${sets.join(', ')}\n RETURN d`,\n params\n );\n\n if (result.records.length === 0) {\n throw new Error('Resource not found');\n }\n\n return this.parseResourceNode(result.records[0]!.get('d'));\n } finally {\n await session.close();\n }\n }\n\n async deleteResource(id: ResourceId): Promise<void> {\n const session = this.getSession();\n try {\n // Delete resource and all its annotations\n await session.run(\n `MATCH (d:Resource {id: $id})\n OPTIONAL MATCH (a:Annotation)-[:BELONGS_TO|:REFERENCES]->(d)\n DETACH DELETE d, a`,\n { id }\n );\n } finally {\n await session.close();\n }\n }\n\n async listResources(filter: ResourceFilter): Promise<{ resources: ResourceDescriptor[]; total: number }> {\n const session = this.getSession();\n try {\n let whereClause = '';\n const params: any = {};\n // Stub nodes are id-only placeholders that `MERGE` creates when a\n // REFERENCES edge points at a resource whose `resource.created` event\n // hasn't landed yet. They carry no name, so they are not listable — and\n // `parseResourceNode` throws on the missing field rather than inventing one.\n const conditions: string[] = ['coalesce(d.stub, false) = false'];\n\n if (filter.archived !== undefined) {\n conditions.push('d.archived = $archived');\n params.archived = filter.archived;\n }\n\n if (filter.entityTypes && filter.entityTypes.length > 0) {\n conditions.push('ANY(type IN $entityTypes WHERE type IN d.entityTypes)');\n params.entityTypes = filter.entityTypes;\n }\n\n // Every term must appear, each satisfiable by the name or the path. A\n // whitespace-only query yields no terms and so is not a search at all.\n const terms = filter.search ? searchTerms(filter.search) : [];\n if (terms.length > 0) {\n conditions.push(\n `ALL(t IN $terms WHERE toLower(d.name) CONTAINS t\n OR toLower(coalesce(d.storageUri, \"\")) CONTAINS t\n OR ANY(e IN coalesce(d.entityTypes, []) WHERE toLower(e) CONTAINS t))`\n );\n params.terms = terms;\n params.search = filter.search!.trim().toLowerCase();\n }\n\n if (conditions.length > 0) {\n whereClause = 'WHERE ' + conditions.join(' AND ');\n }\n\n // Get total count\n const countResult = await session.run(\n `MATCH (d:Resource) ${whereClause} RETURN count(d) as total`,\n params\n );\n const total = countResult.records[0]!.get('total').toNumber();\n\n // Get paginated results - ensure integers for Neo4j\n params.skip = this.neo4j.int(filter.offset || 0);\n params.limit = this.neo4j.int(filter.limit || 20);\n\n // Rank only means something against a query; an unsearched listing orders\n // on recency alone. Ranking must happen here rather than over the returned\n // page, or it would sort one page instead of the match set.\n const rankClause = terms.length > 0\n ? `WITH d, CASE\n WHEN toLower(d.name) = $search THEN 0\n WHEN toLower(d.name) STARTS WITH $search THEN 1\n WHEN ALL(t IN $terms WHERE toLower(d.name) CONTAINS t) THEN 2\n ELSE 3\n END AS rank\n `\n : '';\n const orderClause = terms.length > 0\n ? 'ORDER BY rank, d.created DESC, d.id'\n : 'ORDER BY d.created DESC, d.id';\n\n const result = await session.run(\n `MATCH (d:Resource) ${whereClause}\n ${rankClause}RETURN d\n ${orderClause}\n SKIP $skip LIMIT $limit`,\n params\n );\n\n const resources = result.records.map(record => this.parseResourceNode(record.get('d')));\n\n return { resources, total };\n } finally {\n await session.close();\n }\n }\n\n\n async createAnnotation(input: CreateAnnotationInternal): Promise<Annotation> {\n const session = this.getSession();\n try {\n const annotation = buildAnnotation(input, new Date().toISOString());\n const props = encodeAnnotation(annotation);\n const targetSource = props.resourceId!;\n const bodySource = props.source;\n\n // Entity tags are edges, not properties, so they travel beside the bag.\n const entityTypes = getEntityTypes(input);\n\n // Convert motivation to label (e.g., \"linking\" -> \"Linking\")\n const motivationLabel = motivationToLabel(annotation.motivation);\n\n // The codec's property bag is applied verbatim; `created` is then\n // re-set as a native temporal, which is the one property this store\n // stores in a type of its own.\n const cypher = bodySource\n ? `MATCH (from:Resource {id: $targetSource})\n MATCH (to:Resource {id: $bodySource})\n CREATE (a:Annotation:${motivationLabel})\n SET a = $props, a.created = datetime($created)\n CREATE (a)-[:BELONGS_TO]->(from)\n CREATE (a)-[:REFERENCES]->(to)\n FOREACH (entityType IN $entityTypes |\n MERGE (et:EntityType {name: entityType})\n CREATE (a)-[:TAGGED_AS]->(et)\n )\n RETURN a`\n : `MATCH (d:Resource {id: $targetSource})\n CREATE (a:Annotation:${motivationLabel})\n SET a = $props, a.created = datetime($created)\n CREATE (a)-[:BELONGS_TO]->(d)\n FOREACH (entityType IN $entityTypes |\n MERGE (et:EntityType {name: entityType})\n CREATE (a)-[:TAGGED_AS]->(et)\n )\n RETURN a`;\n\n const result = await session.run(cypher, {\n props,\n created: annotation.created,\n targetSource,\n bodySource: bodySource ?? null,\n entityTypes,\n });\n\n if (result.records.length === 0) {\n throw new Error(`Failed to create annotation: Resource ${targetSource} not found in graph database`);\n }\n\n return parseAnnotationNode(result.records[0]!.get('a'), entityTypes);\n } finally {\n await session.close();\n }\n }\n\n async getAnnotation(id: AnnotationId): Promise<Annotation | null> {\n this.logger?.debug('Getting annotation', { id });\n const session = this.getSession();\n try {\n const result = await session.run(\n `MATCH (a:Annotation {id: $id})\n OPTIONAL MATCH (a)-[:TAGGED_AS]->(et:EntityType)\n RETURN a, collect(et.name) as entityTypes`,\n { id }\n );\n\n if (result.records.length === 0) {\n this.logger?.debug('Annotation not found', { id });\n return null;\n }\n this.logger?.debug('Annotation found', { id });\n return parseAnnotationNode(\n result.records[0]!.get('a'),\n result.records[0]!.get('entityTypes')\n );\n } finally {\n await session.close();\n }\n }\n\n async updateAnnotation(id: AnnotationId, updates: Partial<Annotation>): Promise<Annotation> {\n const session = this.getSession();\n try {\n const setClauses: string[] = ['a.updatedAt = datetime()'];\n const params: any = { id };\n\n // Build SET clauses dynamically\n Object.entries(updates).forEach(([key, value]) => {\n if (key !== 'id' && key !== 'updatedAt') {\n setClauses.push(`a.${key} = $${key}`);\n if (key === 'body') {\n params[key] = JSON.stringify(value);\n } else if (key === 'created') {\n params[key] = value ? new Date(value as any).toISOString() : null;\n } else {\n params[key] = value;\n }\n }\n });\n\n // Update annotation properties\n const result = await session.run(\n `MATCH (a:Annotation {id: $id})\n SET ${setClauses.join(', ')}\n WITH a\n OPTIONAL MATCH (a)-[:TAGGED_AS]->(et:EntityType)\n RETURN a, collect(et.name) as entityTypes`,\n params\n );\n\n if (result.records.length === 0) {\n throw new Error('Annotation not found');\n }\n\n // If motivation was updated, update the label\n if (updates.motivation) {\n const newLabel = motivationToLabel(updates.motivation);\n this.logger?.debug('Updating motivation label', { newLabel });\n\n // Remove all possible motivation labels and add the new one\n const allMotivations = ['Assessing', 'Bookmarking', 'Classifying', 'Commenting',\n 'Describing', 'Editing', 'Highlighting', 'Identifying',\n 'Linking', 'Moderating', 'Questioning', 'Replying', 'Tagging'];\n const removeLabels = allMotivations.filter(m => m !== newLabel).map(m => `a:${m}`).join(', ');\n\n await session.run(\n `MATCH (a:Annotation {id: $id})\n REMOVE ${removeLabels}\n SET a:${newLabel}`,\n { id }\n );\n this.logger?.debug('Motivation label updated', { newLabel });\n }\n\n // If body was updated and contains a SpecificResource, create REFERENCES relationship\n if (updates.body) {\n this.logger?.debug('Body update for annotation', { id, body: updates.body });\n const bodyArray = Array.isArray(updates.body) ? updates.body : [updates.body];\n\n const specificResource = bodyArray.find((item: any) => item.type === 'SpecificResource' && item.purpose === 'linking');\n\n if (specificResource && 'source' in specificResource && specificResource.source) {\n this.logger?.debug('Creating REFERENCES edge', { annotationId: id, targetResourceId: specificResource.source });\n // Create REFERENCES relationship to the target resource\n // Use MERGE for target to create stub node if it doesn't exist yet (eventual consistency)\n // Stub will be enriched when resource.created event arrives\n const refResult = await session.run(\n `MATCH (a:Annotation {id: $annotationId})\n MERGE (target:Resource {id: $targetResourceId})\n ON CREATE SET target.stub = true\n MERGE (a)-[:REFERENCES]->(target)\n RETURN a, target, target.stub AS wasStub`,\n {\n annotationId: id,\n targetResourceId: specificResource.source\n }\n );\n\n if (refResult.records.length > 0) {\n const wasStub = refResult.records[0]!.get('wasStub');\n if (wasStub) {\n this.logger?.debug('REFERENCES edge created with stub node', { targetResourceId: specificResource.source });\n } else {\n this.logger?.debug('REFERENCES edge created to existing resource', { targetResourceId: specificResource.source });\n }\n } else {\n this.logger?.warn('REFERENCES edge creation returned no records');\n }\n } else {\n this.logger?.debug('No SpecificResource in body - stub reference not yet resolved');\n }\n } else {\n this.logger?.debug('No body update for annotation', { id });\n }\n\n return parseAnnotationNode(\n result.records[0]!.get('a'),\n result.records[0]!.get('entityTypes')\n );\n } finally {\n await session.close();\n }\n }\n\n async deleteAnnotation(id: AnnotationId): Promise<void> {\n const session = this.getSession();\n try {\n await session.run(\n 'MATCH (a:Annotation {id: $id}) DETACH DELETE a',\n { id }\n );\n } finally {\n await session.close();\n }\n }\n\n async listAnnotations(filter: { resourceId?: ResourceId; type?: AnnotationCategory }): Promise<{ annotations: Annotation[]; total: number }> {\n const session = this.getSession();\n try {\n const conditions: string[] = [];\n const params: any = {};\n\n if (filter.resourceId) {\n conditions.push('a.resourceId = $resourceId');\n params.resourceId = filter.resourceId;\n }\n\n if (filter.type) {\n conditions.push('a.type = $type');\n params.type = storedAnnotationType(motivationForCategory(filter.type));\n }\n\n const whereClause = conditions.length > 0 ? 'WHERE ' + conditions.join(' AND ') : '';\n\n // Get all results (no pagination in new simplified interface)\n const result = await session.run(\n `MATCH (a:Annotation) ${whereClause}\n OPTIONAL MATCH (a)-[:TAGGED_AS]->(et:EntityType)\n RETURN a, collect(et.name) as entityTypes`,\n params\n );\n\n const annotations = result.records.map(record =>\n parseAnnotationNode(record.get('a'), record.get('entityTypes'))\n );\n\n return { annotations, total: annotations.length };\n } finally {\n await session.close();\n }\n }\n\n async getHighlights(resourceId: ResourceId): Promise<Annotation[]> {\n const session = this.getSession();\n try {\n const result = await session.run(\n `MATCH (a:Annotation {resourceId: $resourceId})\n WHERE a.annotationCategory = 'highlight'\n OPTIONAL MATCH (a)-[:TAGGED_AS]->(et:EntityType)\n RETURN a, collect(et.name) as entityTypes\n ORDER BY a.created DESC`,\n { resourceId }\n );\n\n return result.records.map(record =>\n parseAnnotationNode(record.get('a'), record.get('entityTypes'))\n );\n } finally {\n await session.close();\n }\n }\n\n async resolveReference(annotationId: AnnotationId, source: ResourceId): Promise<Annotation> {\n const session = this.getSession();\n try {\n // Get the target resource's name\n const docResult = await session.run(\n 'MATCH (d:Resource {id: $id}) RETURN d.name as name',\n { id: source }\n );\n const resourceName = docResult.records[0]?.get('name');\n\n // Update annotation and create REFERENCES relationship\n const result = await session.run(\n `MATCH (a:Annotation {id: $annotationId})\n MATCH (to:Resource {id: $source})\n SET a.source = $source,\n a.resolvedResourceName = $resourceName,\n a.resolvedAt = datetime()\n MERGE (a)-[:REFERENCES]->(to)\n OPTIONAL MATCH (a)-[:TAGGED_AS]->(et:EntityType)\n RETURN a, collect(et.name) as entityTypes`,\n { annotationId, source, resourceName }\n );\n\n if (result.records.length === 0) {\n throw new Error('Annotation not found');\n }\n\n return parseAnnotationNode(\n result.records[0]!.get('a'),\n result.records[0]!.get('entityTypes')\n );\n } finally {\n await session.close();\n }\n }\n\n async getReferences(resourceId: ResourceId): Promise<Annotation[]> {\n const session = this.getSession();\n try {\n const result = await session.run(\n `MATCH (a:Annotation {resourceId: $resourceId})\n WHERE a.annotationCategory IN ['stub_reference', 'resolved_reference']\n OPTIONAL MATCH (a)-[:TAGGED_AS]->(et:EntityType)\n RETURN a, collect(et.name) as entityTypes\n ORDER BY a.created DESC`,\n { resourceId }\n );\n\n return result.records.map(record =>\n parseAnnotationNode(record.get('a'), record.get('entityTypes'))\n );\n } finally {\n await session.close();\n }\n }\n\n async getEntityReferences(resourceId: ResourceId, entityTypes?: string[]): Promise<Annotation[]> {\n const session = this.getSession();\n try {\n let cypher = `MATCH (a:Annotation {resourceId: $resourceId})\n WHERE a.source IS NOT NULL`;\n\n const params: any = { resourceId };\n\n if (entityTypes && entityTypes.length > 0) {\n cypher += `\n MATCH (a)-[:TAGGED_AS]->(et:EntityType)\n WHERE et.name IN $entityTypes`;\n params.entityTypes = entityTypes;\n }\n\n cypher += `\n OPTIONAL MATCH (a)-[:TAGGED_AS]->(et2:EntityType)\n RETURN a, collect(et2.name) as entityTypes\n ORDER BY a.created DESC`;\n\n const result = await session.run(cypher, params);\n\n return result.records.map(record =>\n parseAnnotationNode(record.get('a'), record.get('entityTypes'))\n );\n } finally {\n await session.close();\n }\n }\n\n async getResourceAnnotations(resourceId: ResourceId): Promise<Annotation[]> {\n const session = this.getSession();\n try {\n const result = await session.run(\n `MATCH (a:Annotation {resourceId: $resourceId})\n OPTIONAL MATCH (a)-[:TAGGED_AS]->(et:EntityType)\n RETURN a, collect(et.name) as entityTypes\n ORDER BY a.created DESC`,\n { resourceId }\n );\n\n return result.records.map(record =>\n parseAnnotationNode(record.get('a'), record.get('entityTypes'))\n );\n } finally {\n await session.close();\n }\n }\n\n async getResourceReferencedBy(resourceId: ResourceId, motivation?: string): Promise<Annotation[]> {\n const session = this.getSession();\n try {\n this.logger?.debug('Searching for annotations referencing resource', { resourceId, motivation });\n\n // Build query with optional motivation label filter\n // If motivation is specified, use the label for efficient filtering\n const motivationLabel = motivation ? `:${motivationToLabel(motivation)}` : '';\n const cypher = `MATCH (a:Annotation${motivationLabel})-[:REFERENCES]->(d:Resource {id: $resourceId})\n OPTIONAL MATCH (a)-[:TAGGED_AS]->(et:EntityType)\n RETURN a, collect(et.name) as entityTypes\n ORDER BY a.created DESC`;\n\n const result = await session.run(cypher, { resourceId });\n\n this.logger?.debug('Found annotations', { count: result.records.length });\n\n return result.records.map(record =>\n parseAnnotationNode(record.get('a'), record.get('entityTypes'))\n );\n } finally {\n await session.close();\n }\n }\n\n async getResourceConnections(resourceId: ResourceId): Promise<GraphConnection[]> {\n const session = this.getSession();\n try {\n const result = await session.run(\n `MATCH (d:Resource {id: $resourceId})\n OPTIONAL MATCH (d)<-[:BELONGS_TO]-(a1:Annotation)-[:REFERENCES]->(other:Resource)\n OPTIONAL MATCH (other)<-[:BELONGS_TO]-(a2:Annotation)-[:REFERENCES]->(d)\n WITH other, COLLECT(DISTINCT a1) as outgoing, COLLECT(DISTINCT a2) as incoming\n WHERE other IS NOT NULL\n RETURN other, outgoing, incoming`,\n { resourceId }\n );\n\n const connections: GraphConnection[] = [];\n\n for (const record of result.records) {\n const targetResource = this.parseResourceNode(record.get('other'));\n\n // Fetch entity types for outgoing annotations\n const outgoingNodes = record.get('outgoing');\n const outgoing: Annotation[] = [];\n for (const annNode of outgoingNodes) {\n const annId = annNode.properties.id;\n const annResult = await session.run(\n `MATCH (a:Annotation {id: $id})\n OPTIONAL MATCH (a)-[:TAGGED_AS]->(et:EntityType)\n RETURN a, collect(et.name) as entityTypes`,\n { id: annId }\n );\n if (annResult.records.length > 0) {\n outgoing.push(parseAnnotationNode(\n annResult.records[0]!.get('a'),\n annResult.records[0]!.get('entityTypes')\n ));\n }\n }\n\n // Fetch entity types for incoming annotations\n const incomingNodes = record.get('incoming');\n const incoming: Annotation[] = [];\n for (const annNode of incomingNodes) {\n const annId = annNode.properties.id;\n const annResult = await session.run(\n `MATCH (a:Annotation {id: $id})\n OPTIONAL MATCH (a)-[:TAGGED_AS]->(et:EntityType)\n RETURN a, collect(et.name) as entityTypes`,\n { id: annId }\n );\n if (annResult.records.length > 0) {\n incoming.push(parseAnnotationNode(\n annResult.records[0]!.get('a'),\n annResult.records[0]!.get('entityTypes')\n ));\n }\n }\n\n connections.push({\n targetResource,\n annotations: outgoing,\n bidirectional: incoming.length > 0\n });\n }\n\n return connections;\n } finally {\n await session.close();\n }\n }\n\n async findPath(fromResourceId: string, toResourceId: string, maxDepth: number = 5): Promise<GraphPath[]> {\n const session = this.getSession();\n try {\n const result = await session.run(\n `MATCH path = shortestPath((from:Resource {id: $fromId})-[:REFERENCES*..${maxDepth}]-(to:Resource {id: $toId}))\n WITH path, nodes(path) as docs, relationships(path) as rels\n RETURN docs, rels\n LIMIT 10`,\n { fromId: fromResourceId, toId: toResourceId }\n );\n\n const paths: GraphPath[] = [];\n\n for (const record of result.records) {\n const docs = record.get('docs').map((node: any) => this.parseResourceNode(node));\n const rels = record.get('rels');\n\n // Get annotation details for the relationships\n const annotationIds = rels.map((rel: any) => rel.properties.id).filter((id: any) => id);\n const annotations: Annotation[] = [];\n\n if (annotationIds.length > 0) {\n const selResult = await session.run(\n `MATCH (a:Annotation) WHERE a.id IN $ids\n OPTIONAL MATCH (a)-[:TAGGED_AS]->(et:EntityType)\n RETURN a, collect(et.name) as entityTypes`,\n { ids: annotationIds }\n );\n selResult.records.forEach(rec => {\n annotations.push(parseAnnotationNode(\n rec.get('a'),\n rec.get('entityTypes')\n ));\n });\n }\n\n paths.push({\n resources: docs,\n annotations: annotations\n });\n }\n\n return paths;\n } finally {\n await session.close();\n }\n }\n\n async getEntityTypeStats(): Promise<EntityTypeStats[]> {\n const session = this.getSession();\n try {\n const result = await session.run(\n `MATCH (d:Resource)\n UNWIND d.entityTypes AS type\n RETURN type, count(*) AS count\n ORDER BY count DESC`\n );\n\n return result.records.map(record => ({\n type: record.get('type'),\n count: record.get('count').toNumber()\n }));\n } finally {\n await session.close();\n }\n }\n\n async getStats(): Promise<{\n resourceCount: number;\n annotationCount: number;\n highlightCount: number;\n referenceCount: number;\n entityReferenceCount: number;\n entityTypes: Record<string, number>;\n contentTypes: Record<string, number>;\n }> {\n const session = this.getSession();\n try {\n // Get resource count\n const docCountResult = await session.run('MATCH (d:Resource) RETURN count(d) as count');\n const resourceCount = docCountResult.records[0]!.get('count').toNumber();\n\n // Get annotation counts\n const selCountResult = await session.run('MATCH (a:Annotation) RETURN count(a) as count');\n const annotationCount = selCountResult.records[0]!.get('count').toNumber();\n\n const highlightCountResult = await session.run(\n 'MATCH (a:Annotation) WHERE a.resolvedResourceId IS NULL RETURN count(a) as count'\n );\n const highlightCount = highlightCountResult.records[0]!.get('count').toNumber();\n\n const referenceCountResult = await session.run(\n 'MATCH (a:Annotation) WHERE a.resolvedResourceId IS NOT NULL RETURN count(a) as count'\n );\n const referenceCount = referenceCountResult.records[0]!.get('count').toNumber();\n\n const entityRefCountResult = await session.run(\n 'MATCH (a:Annotation) WHERE a.resolvedResourceId IS NOT NULL AND size(a.entityTypes) > 0 RETURN count(a) as count'\n );\n const entityReferenceCount = entityRefCountResult.records[0]!.get('count').toNumber();\n\n // Get entity type stats\n const entityTypeResult = await session.run(\n `MATCH (d:Resource)\n UNWIND d.entityTypes AS type\n RETURN type, count(*) AS count`\n );\n\n const entityTypes: Record<string, number> = {};\n entityTypeResult.records.forEach(record => {\n entityTypes[record.get('type')] = record.get('count').toNumber();\n });\n\n // Get content type stats\n const contentTypeResult = await session.run(\n `MATCH (d:Resource)\n RETURN d.format as type, count(*) AS count`\n );\n\n const contentTypes: Record<string, number> = {};\n contentTypeResult.records.forEach(record => {\n contentTypes[record.get('type')] = record.get('count').toNumber();\n });\n\n return {\n resourceCount,\n annotationCount,\n highlightCount,\n referenceCount,\n entityReferenceCount,\n entityTypes,\n contentTypes\n };\n } finally {\n await session.close();\n }\n }\n\n async batchCreateResources(resources: ResourceDescriptor[]): Promise<ResourceDescriptor[]> {\n if (resources.length === 0) return [];\n const session = this.getSession();\n try {\n const params = resources.map(resource => {\n const primaryRep = getPrimaryRepresentation(resource);\n if (!primaryRep) throw new Error('Resource must have at least one representation');\n return {\n id: resource['@id'],\n name: resource.name,\n entityTypes: resource.entityTypes,\n format: primaryRep.mediaType,\n archived: resource.archived || false,\n created: resource.dateCreated,\n creator: JSON.stringify(resource.wasAttributedTo),\n contentChecksum: primaryRep.checksum,\n sourceAnnotationId: resource.sourceAnnotationId ?? null,\n sourceResourceId: resource.sourceResourceId ?? null,\n storageUri: getStorageUri(resource) ?? null,\n };\n });\n\n const result = await session.run(\n `UNWIND $resources AS r\n MERGE (d:Resource {id: r.id})\n SET d.name = r.name,\n d.entityTypes = r.entityTypes,\n d.format = r.format,\n d.archived = r.archived,\n d.created = datetime(r.created),\n d.creator = r.creator,\n d.contentChecksum = r.contentChecksum,\n d.sourceAnnotationId = r.sourceAnnotationId,\n d.sourceResourceId = r.sourceResourceId,\n d.storageUri = r.storageUri,\n d.stub = false\n RETURN d`,\n { resources: params }\n );\n\n this.logger?.info('Batch created/enriched resources', { count: resources.length });\n return result.records.map(record => this.parseResourceNode(record.get('d')));\n } finally {\n await session.close();\n }\n }\n\n async createAnnotations(inputs: CreateAnnotationInternal[]): Promise<Annotation[]> {\n const results: Annotation[] = [];\n for (const input of inputs) {\n results.push(await this.createAnnotation(input));\n }\n return results;\n }\n\n async resolveReferences(inputs: { annotationId: AnnotationId; source: ResourceId }[]): Promise<Annotation[]> {\n const results: Annotation[] = [];\n for (const input of inputs) {\n results.push(await this.resolveReference(input.annotationId, input.source));\n }\n return results;\n }\n\n async detectAnnotations(_resourceId: ResourceId): Promise<Annotation[]> {\n // This would use AI/ML to detect annotations in a resource\n // For now, return empty array as a placeholder\n return [];\n }\n\n // Tag Collections\n async getEntityTypes(): Promise<string[]> {\n if (this.entityTypesCollection === null) {\n await this.initializeTagCollections();\n }\n return Array.from(this.entityTypesCollection!).sort();\n }\n\n async addEntityType(tag: string): Promise<void> {\n if (this.entityTypesCollection === null) {\n await this.initializeTagCollections();\n }\n this.entityTypesCollection!.add(tag);\n await this.persistTagCollection('entity-types', this.entityTypesCollection!);\n }\n\n async addEntityTypes(tags: string[]): Promise<void> {\n if (this.entityTypesCollection === null) {\n await this.initializeTagCollections();\n }\n tags.forEach(tag => this.entityTypesCollection!.add(tag));\n await this.persistTagCollection('entity-types', this.entityTypesCollection!);\n }\n\n private async initializeTagCollections(): Promise<void> {\n const session = this.getSession();\n try {\n // Load existing collections from Neo4j\n const result = await session.run(\n 'MATCH (t:TagCollection {type: \"entity-types\"}) RETURN t.tags as tags'\n );\n\n let entityTypesFromDb: string[] = [];\n\n if (result.records.length > 0) {\n const record = result.records[0];\n if (record) {\n const tags = record.get('tags');\n entityTypesFromDb = tags || [];\n }\n }\n\n // Load defaults\n const { DEFAULT_ENTITY_TYPES } = await import('@semiont/ontology');\n\n // Merge with defaults\n this.entityTypesCollection = new Set([...DEFAULT_ENTITY_TYPES, ...entityTypesFromDb]);\n\n // Persist merged collection back to Neo4j\n await this.persistTagCollection('entity-types', this.entityTypesCollection);\n } finally {\n await session.close();\n }\n }\n\n private async persistTagCollection(type: string, collection: Set<string>): Promise<void> {\n const session = this.getSession();\n try {\n await session.run(\n 'MERGE (t:TagCollection {type: $type}) SET t.tags = $tags',\n { type, tags: Array.from(collection) }\n );\n } finally {\n await session.close();\n }\n }\n\n generateId(): string {\n return uuidv4().replace(/-/g, '').substring(0, 12);\n }\n\n async clearDatabase(): Promise<void> {\n const session = this.getSession();\n try {\n // CAREFUL! This clears the entire database\n await session.run('MATCH (n) DETACH DELETE n');\n this.entityTypesCollection = null;\n } finally {\n await session.close();\n }\n }\n\n // Helper methods to parse Neo4j nodes\n private parseResourceNode(node: any): ResourceDescriptor {\n const props = node.properties;\n\n // Validate all required fields\n if (!props.id) throw new Error('Resource missing required field: id');\n if (!props.name) throw new Error(`Resource ${props.id} missing required field: name`);\n if (!props.entityTypes) throw new Error(`Resource ${props.id} missing required field: entityTypes`);\n if (!props.format) throw new Error(`Resource ${props.id} missing required field: contentType`);\n if (props.archived === undefined || props.archived === null) throw new Error(`Resource ${props.id} missing required field: archived`);\n if (!props.created) throw new Error(`Resource ${props.id} missing required field: created`);\n if (!props.creator) throw new Error(`Resource ${props.id} missing required field: creator`);\n if (!props.contentChecksum) throw new Error(`Resource ${props.id} missing required field: contentChecksum`);\n\n const resource: ResourceDescriptor = {\n '@context': 'https://schema.org/',\n '@id': props.id,\n name: props.name,\n entityTypes: props.entityTypes,\n representations: [{\n mediaType: props.format,\n checksum: props.contentChecksum,\n rel: 'original',\n storageUri: props.storageUri ?? undefined,\n }],\n archived: props.archived,\n dateCreated: props.created.toString(),\n wasAttributedTo: typeof props.creator === 'string' ? JSON.parse(props.creator) : props.creator,\n };\n\n if (props.sourceResourceId) resource.sourceResourceId = props.sourceResourceId;\n\n return resource;\n }\n\n}\n\n/**\n * Project a neo4j annotation node to the wire `Annotation`.\n *\n * Module-level (not a method) so the projection is unit-testable without a\n * driver: `node` is untyped at this seam, which is exactly how a native\n * neo4j DateTime once reached the wire as `created` unseen by tsc.\n */\nexport function parseAnnotationNode(node: any, entityTypes: string[] = []): Annotation {\n return decodeAnnotation(normalizeProperties(node.properties), entityTypes);\n}\n\n/**\n * Flatten a node's properties to the strings the codec reads.\n *\n * `created` is stored as `datetime($created)`, so the driver hands back a\n * native temporal object whose `toString()` is the ISO form — the coercion\n * that has to happen before the codec sees a value it is entitled to treat\n * as a string. This seam is untyped, so only a test can see it slip.\n */\nfunction normalizeProperties(props: any): AnnotationProperties {\n const normalized: AnnotationProperties = {};\n for (const [key, value] of Object.entries(props ?? {})) {\n if (value === null || value === undefined) continue;\n normalized[key] = typeof value === 'string' ? value : String(value);\n }\n return normalized;\n}\n","// JanusGraph implementation with real Gremlin connection\n// This replaces the mock in-memory implementation\n\nimport { GraphDatabase } from '../interface';\nimport { assertMutableResourceUpdate } from '../interface';\nimport { queryResources } from '../resource-query';\nimport type { Logger } from '@semiont/core';\nimport { resourceId as makeResourceId } from '@semiont/core';\nimport { getBodySource, getPrimaryRepresentation, getResourceId, getStorageUri } from '@semiont/core';\nimport { getEntityTypes } from '@semiont/ontology';\nimport type {\n AnnotationCategory,\n GraphConnection,\n GraphPath,\n EntityTypeStats,\n ResourceFilter,\n UpdateResourceInput,\n CreateAnnotationInternal,\n ResourceId,\n AnnotationId,\n} from '@semiont/core';\nimport { v4 as uuidv4 } from 'uuid';\nimport {\n buildAnnotation,\n decodeAnnotation,\n encodeAnnotation,\n encodeSelector,\n motivationForCategory,\n storedAnnotationType,\n type AnnotationProperties,\n} from '../annotation-codec';\n\nimport type { ResourceDescriptor } from '@semiont/core';\nimport type { Annotation } from '@semiont/core';\n\n/** Helper to get property value from Gremlin vertex properties */\nfunction getPropertyValue(props: any, key: string): any {\n if (!props[key]) return undefined;\n const prop = Array.isArray(props[key]) ? props[key][0] : props[key];\n return prop?.value || prop;\n}\n\n/**\n * Convert a JanusGraph vertex to an Annotation.\n *\n * Module-level so the cross-store conformance suite can run this store's\n * decode path with no live JanusGraph: everything past the flattening is the\n * shared codec's. This is where a missing selector used to become `'{}'` and\n * a missing motivation used to become `'linking'`.\n */\nexport function vertexToAnnotation(vertex: any, entityTypes: string[] = []): Annotation {\n const props = vertex.properties || {};\n const normalized: AnnotationProperties = {};\n for (const key of Object.keys(props)) {\n const value = getPropertyValue(props, key);\n if (value === undefined || value === null) continue;\n normalized[key] = typeof value === 'string' ? value : String(value);\n }\n return decodeAnnotation(normalized, entityTypes);\n}\n\nexport class JanusGraphDatabase implements GraphDatabase {\n private connected: boolean = false;\n private connection: any | null = null;\n private g: any | null = null;\n private logger?: Logger;\n\n // Tag Collections - cached in memory for performance\n private entityTypesCollection: Set<string> | null = null;\n\n\n constructor(\n private graphConfig: {\n host?: string;\n port?: number;\n storageBackend?: 'cassandra' | 'hbase' | 'berkeleydb';\n indexBackend?: 'elasticsearch' | 'solr' | 'lucene';\n logger?: Logger;\n },\n ) {\n this.logger = graphConfig.logger;\n }\n \n async connect(): Promise<void> {\n // Configuration must be provided via constructor\n const host = this.graphConfig.host;\n if (!host) {\n throw new Error('JanusGraph host is required: provide in config');\n }\n\n const port = this.graphConfig.port;\n if (!port) {\n throw new Error('JanusGraph port is required: provide in config');\n }\n\n this.logger?.info('Connecting to JanusGraph', { host, port });\n\n const gremlin = await import('gremlin');\n const DriverRemoteConnection = gremlin.driver.DriverRemoteConnection;\n const traversal = gremlin.process.AnonymousTraversalSource.traversal;\n\n this.connection = new DriverRemoteConnection(\n `ws://${host}:${port}/gremlin`,\n {}\n );\n\n this.g = traversal().withRemote(this.connection);\n\n // Test the connection with a simple query\n await this.g.V().limit(1).toList();\n\n this.connected = true;\n this.logger?.info('Successfully connected to JanusGraph');\n\n // Initialize schema if needed\n await this.initializeSchema();\n }\n \n async disconnect(): Promise<void> {\n if (this.connection) {\n await this.connection.close();\n }\n this.connected = false;\n }\n \n isConnected(): boolean {\n return this.connected;\n }\n \n private async initializeSchema(): Promise<void> {\n // Note: Schema management in JanusGraph typically requires direct access\n // to the management API, which isn't available through Gremlin.\n // In production, you'd run schema initialization scripts separately.\n this.logger?.debug('Schema initialization would happen here in production');\n }\n \n // Helper function to convert vertex to Resource\n private vertexToResource(vertex: any): ResourceDescriptor {\n const props = vertex.properties || {};\n const id = getPropertyValue(props, 'id');\n\n // Validate required fields\n const creatorRaw = getPropertyValue(props, 'creator');\n const contentChecksum = getPropertyValue(props, 'contentChecksum');\n const mediaType = getPropertyValue(props, 'contentType');\n\n if (!creatorRaw) throw new Error(`Resource ${id} missing required field: creator`);\n if (!contentChecksum) throw new Error(`Resource ${id} missing required field: contentChecksum`);\n if (!mediaType) throw new Error(`Resource ${id} missing required field: contentType`);\n\n const creator = typeof creatorRaw === 'string' ? JSON.parse(creatorRaw) : creatorRaw;\n\n const resource: ResourceDescriptor = {\n '@context': 'https://schema.org/',\n '@id': id,\n name: getPropertyValue(props, 'name'),\n entityTypes: JSON.parse(getPropertyValue(props, 'entityTypes') || '[]'),\n representations: [{\n mediaType,\n checksum: contentChecksum,\n rel: 'original',\n storageUri: getPropertyValue(props, 'storageUri') || undefined,\n }],\n archived: getPropertyValue(props, 'archived') === 'true',\n dateCreated: getPropertyValue(props, 'created'),\n wasAttributedTo: creator,\n };\n\n const sourceAnnotationId = getPropertyValue(props, 'sourceAnnotationId');\n const sourceResourceId = getPropertyValue(props, 'sourceResourceId');\n\n if (sourceAnnotationId) resource.sourceAnnotationId = sourceAnnotationId;\n if (sourceResourceId) resource.sourceResourceId = sourceResourceId;\n\n return resource;\n }\n \n // Helper method to fetch annotations with their entity types\n private async fetchAnnotationsWithEntityTypes(annotationVertices: any[]): Promise<Annotation[]> {\n const annotations: Annotation[] = [];\n\n for (const vertex of annotationVertices) {\n const id = getPropertyValue(vertex.properties || {}, 'id');\n\n // Fetch entity types for this annotation\n const entityTypeVertices = await this.g!\n .V()\n .has('Annotation', 'id', id)\n .out('TAGGED_AS')\n .has('EntityType')\n .toList();\n\n const entityTypes = entityTypeVertices.map((v: any) =>\n getPropertyValue(v.properties || {}, 'name')\n ).filter(Boolean);\n\n annotations.push(vertexToAnnotation(vertex, entityTypes));\n }\n\n return annotations;\n }\n\n\n async createResource(resource: ResourceDescriptor): Promise<ResourceDescriptor> {\n const id = getResourceId(resource);\n const primaryRep = getPrimaryRepresentation(resource);\n if (!primaryRep) {\n throw new Error('Resource must have at least one representation');\n }\n\n // Create vertex in JanusGraph using fields from ResourceDescriptor\n const vertex = this.g!\n .addV('Resource')\n .property('id', id)\n .property('name', resource.name)\n .property('entityTypes', JSON.stringify(resource.entityTypes))\n .property('contentType', primaryRep.mediaType)\n .property('archived', resource.archived || false)\n .property('created', resource.dateCreated)\n .property('creator', JSON.stringify(resource.wasAttributedTo))\n .property('contentChecksum', primaryRep.checksum);\n\n if (resource.sourceAnnotationId) {\n vertex.property('sourceAnnotationId', resource.sourceAnnotationId);\n }\n if (resource.sourceResourceId) {\n vertex.property('sourceResourceId', resource.sourceResourceId);\n }\n const storageUri = getStorageUri(resource);\n if (storageUri) {\n vertex.property('storageUri', storageUri);\n }\n\n await vertex.next();\n\n this.logger?.info('Created resource vertex in JanusGraph', { id });\n return resource;\n }\n \n async getResource(id: ResourceId): Promise<ResourceDescriptor | null> {\n const vertices = await this.g!\n .V()\n .has('Resource', 'id', id)\n .toList();\n\n if (vertices.length === 0) {\n return null;\n }\n\n return this.vertexToResource(vertices[0] as any);\n }\n \n async updateResource(id: ResourceId, input: UpdateResourceInput): Promise<ResourceDescriptor> {\n assertMutableResourceUpdate(input);\n\n let traversal = this.g!\n .V()\n .has('Resource', 'id', id);\n if (input.archived !== undefined) {\n traversal = traversal.property('archived', input.archived);\n }\n if (input.entityTypes !== undefined) {\n // Mirrors createResource's storage idiom: entityTypes ride as JSON.\n traversal = traversal.property('entityTypes', JSON.stringify(input.entityTypes));\n }\n await traversal.next();\n\n const updatedResource = await this.getResource(id);\n if (!updatedResource) {\n throw new Error('Resource not found');\n }\n\n return updatedResource;\n }\n \n async deleteResource(id: ResourceId): Promise<void> {\n // Delete the vertex and all its edges\n await this.g!\n .V()\n .has('Resource', 'id', id)\n .drop()\n .next();\n\n this.logger?.info('Deleted resource from JanusGraph', { id });\n }\n \n async listResources(filter: ResourceFilter): Promise<{ resources: ResourceDescriptor[]; total: number }> {\n // Note: filtering is done client-side after retrieval. In production,\n // JanusGraph supports server-side text predicates via Elasticsearch,\n // but composing OR across multiple text properties requires the\n // anonymous-traversal API; for a gateway that's not the production\n // target today, JS post-filtering is simpler and adequate at our scale.\n const docs = await this.g!.V().hasLabel('Resource').toList();\n return queryResources(docs.map((v: any) => this.vertexToResource(v)), filter);\n }\n\n \n async createAnnotation(input: CreateAnnotationInternal): Promise<Annotation> {\n // The caller's id is the system of record's — never mint a fresh one\n // (the event-log id is what deletes and lookups arrive under).\n const annotation = buildAnnotation(input, new Date().toISOString());\n const props = encodeAnnotation(annotation);\n const targetSource = props.resourceId!;\n const bodySource = props.source;\n const entityTypes = getEntityTypes(input);\n\n // Create annotation vertex — every property comes from the codec, so a\n // source-only target contributes no `selector` property at all.\n let vertex = this.g!.addV('Annotation');\n for (const [key, value] of Object.entries(props)) {\n vertex = vertex.property(key, value);\n }\n\n const annVertex = await vertex.next();\n\n // Create edge from annotation to resource (BELONGS_TO)\n await this.g!\n .V(annVertex.value)\n .addE('BELONGS_TO')\n .to(this.g!.V().has('Resource', 'id', targetSource))\n .next();\n\n // If it's a resolved reference, create edge to target resource\n if (bodySource) {\n await this.g!\n .V(annVertex.value)\n .addE('REFERENCES')\n .to(this.g!.V().has('Resource', 'id', bodySource))\n .next();\n }\n\n // Create TAGGED_AS relationships for entity types\n for (const entityType of entityTypes) {\n // Get or create EntityType vertex\n const etResults = await this.g!\n .V()\n .has('EntityType', 'name', entityType)\n .toList();\n\n let etVertex;\n if (etResults.length === 0) {\n // Create new EntityType vertex\n etVertex = await this.g!\n .addV('EntityType')\n .property('name', entityType)\n .next();\n } else {\n etVertex = { value: etResults[0] };\n }\n\n // Create TAGGED_AS edge from Annotation to EntityType\n await this.g!\n .V(annVertex.value)\n .addE('TAGGED_AS')\n .to(this.g!.V(etVertex.value))\n .next();\n }\n\n this.logger?.info('Created annotation in JanusGraph', { id: annotation.id });\n return annotation;\n }\n \n async getAnnotation(id: AnnotationId): Promise<Annotation | null> {\n const vertices = await this.g!\n .V()\n .has('Annotation', 'id', id)\n .toList();\n\n if (vertices.length === 0) {\n return null;\n }\n\n // Fetch entity types from TAGGED_AS relationships\n const entityTypeVertices = await this.g!\n .V()\n .has('Annotation', 'id', id)\n .out('TAGGED_AS')\n .has('EntityType')\n .toList();\n\n const entityTypes = entityTypeVertices.map((v: any) =>\n getPropertyValue(v.properties || {}, 'name')\n ).filter(Boolean);\n\n return vertexToAnnotation(vertices[0] as any, entityTypes);\n }\n \n async updateAnnotation(id: AnnotationId, updates: Partial<Annotation>): Promise<Annotation> {\n const traversalQuery = this.g!\n .V()\n .has('Annotation', 'id', id);\n\n // Update target properties\n if (updates.target !== undefined && typeof updates.target !== 'string') {\n if (updates.target.selector !== undefined) {\n for (const [key, value] of Object.entries(encodeSelector(updates.target.selector))) {\n await traversalQuery.property(key, value).next();\n }\n }\n }\n\n // Update body properties and entity types\n if (updates.body !== undefined) {\n const bodySource = getBodySource(updates.body);\n const entityTypes = getEntityTypes({ body: updates.body });\n\n if (bodySource) {\n await traversalQuery.property('source', bodySource).next();\n }\n\n // Update entity type relationships - remove old ones and create new ones\n if (entityTypes.length >= 0) {\n // Remove existing TAGGED_AS edges\n await this.g!\n .V()\n .has('Annotation', 'id', id)\n .outE('TAGGED_AS')\n .drop()\n .iterate();\n\n // Create new TAGGED_AS edges\n for (const entityType of entityTypes) {\n // Get or create EntityType vertex\n const etResults = await this.g!\n .V()\n .has('EntityType', 'name', entityType)\n .toList();\n\n let etVertex;\n if (etResults.length === 0) {\n // Create new EntityType vertex\n etVertex = await this.g!\n .addV('EntityType')\n .property('name', entityType)\n .next();\n } else {\n etVertex = { value: etResults[0] };\n }\n\n // Create TAGGED_AS edge from Annotation to EntityType\n const annVertices = await this.g!\n .V()\n .has('Annotation', 'id', id)\n .toList();\n\n if (annVertices.length > 0) {\n await this.g!\n .V(annVertices[0])\n .addE('TAGGED_AS')\n .to(this.g!.V(etVertex.value))\n .next();\n }\n }\n }\n }\n\n if (updates.modified !== undefined) {\n await traversalQuery.property('modified', updates.modified).next();\n }\n if (updates.generator !== undefined) {\n await traversalQuery.property('generator', JSON.stringify(updates.generator)).next();\n }\n\n const updatedAnnotation = await this.getAnnotation(id);\n if (!updatedAnnotation) {\n throw new Error('Annotation not found');\n }\n\n return updatedAnnotation;\n }\n \n async deleteAnnotation(id: AnnotationId): Promise<void> {\n await this.g!\n .V()\n .has('Annotation', 'id', id)\n .drop()\n .next();\n\n this.logger?.info('Deleted annotation from JanusGraph', { id });\n }\n \n async listAnnotations(filter: { resourceId?: ResourceId; type?: AnnotationCategory }): Promise<{ annotations: Annotation[]; total: number }> {\n let traversalQuery = this.g!.V().hasLabel('Annotation');\n\n // Apply filters\n if (filter.resourceId) {\n traversalQuery = traversalQuery.has('resourceId', filter.resourceId);\n }\n\n if (filter.type) {\n traversalQuery = traversalQuery.has('type', storedAnnotationType(motivationForCategory(filter.type)));\n }\n\n const vertices = await traversalQuery.toList();\n const annotations = await this.fetchAnnotationsWithEntityTypes(vertices);\n\n return {\n annotations,\n total: annotations.length\n };\n }\n\n async getHighlights(resourceId: ResourceId): Promise<Annotation[]> {\n const { annotations } = await this.listAnnotations({\n resourceId,\n type: 'highlight'\n });\n return annotations;\n }\n\n async resolveReference(annotationId: AnnotationId, source: ResourceId): Promise<Annotation> {\n const annotation = await this.getAnnotation(annotationId);\n if (!annotation) throw new Error('Annotation not found');\n\n // TODO Preserve existing TextualBody entities, add SpecificResource\n // For now, just update with SpecificResource (losing entity tags)\n await this.updateAnnotation(annotationId, {\n body: [\n {\n type: 'SpecificResource',\n source,\n purpose: 'linking' as const,\n },\n ],\n });\n\n // Create edge from annotation to target resource\n await this.g!\n .V()\n .has('Annotation', 'id', annotationId)\n .addE('REFERENCES')\n .to(this.g!.V().has('Resource', 'id', source))\n .next();\n\n const updatedAnnotation = await this.getAnnotation(annotationId);\n if (!updatedAnnotation) {\n throw new Error('Annotation not found after update');\n }\n\n return updatedAnnotation;\n }\n\n async getReferences(resourceId: ResourceId): Promise<Annotation[]> {\n const { annotations } = await this.listAnnotations({\n resourceId,\n type: 'reference'\n });\n return annotations;\n }\n\n async getEntityReferences(resourceId: ResourceId, entityTypes?: string[]): Promise<Annotation[]> {\n const { annotations } = await this.listAnnotations({\n resourceId,\n type: 'reference'\n });\n\n // TODO Extract entity types from body using helper\n if (entityTypes && entityTypes.length > 0) {\n return annotations.filter(ann => {\n const annEntityTypes = getEntityTypes(ann);\n return annEntityTypes.some((type: string) => entityTypes.includes(type));\n });\n }\n\n return annotations.filter(ann => getEntityTypes(ann).length > 0);\n }\n\n async getResourceAnnotations(resourceId: ResourceId): Promise<Annotation[]> {\n const { annotations } = await this.listAnnotations({ resourceId });\n return annotations;\n }\n\n async getResourceReferencedBy(resourceId: ResourceId, _motivation?: string): Promise<Annotation[]> {\n // Find annotations that reference this resource\n const vertices = await this.g!\n .V()\n .hasLabel('Annotation')\n .has('source', resourceId)\n .toList();\n\n return this.fetchAnnotationsWithEntityTypes(vertices);\n }\n \n async getResourceConnections(resourceId: ResourceId): Promise<GraphConnection[]> {\n // Use Gremlin to find connected resources\n const paths = await this.g!\n .V()\n .has('Resource', 'id', resourceId)\n .inE('BELONGS_TO')\n .outV()\n .outE('REFERENCES')\n .inV()\n .path()\n .toList();\n\n // Convert paths to connections\n // This is simplified - real implementation would process paths properly\n this.logger?.debug('Found paths', { count: paths.length });\n\n // For now, also build connections from references\n const connections: GraphConnection[] = [];\n const refs = await this.getReferences(resourceId);\n\n for (const ref of refs) {\n // Extract source from body using helper\n const bodySource = getBodySource(ref.body);\n if (bodySource) {\n const targetDoc = await this.getResource(makeResourceId(bodySource));\n if (targetDoc) {\n const existing = connections.find(c => c.targetResource.id === targetDoc.id);\n if (existing) {\n existing.annotations.push(ref);\n } else {\n connections.push({\n targetResource: targetDoc,\n annotations: [ref],\n relationshipType: undefined,\n bidirectional: false,\n });\n }\n }\n }\n }\n\n return connections;\n }\n \n async findPath(_fromResourceId: string, _toResourceId: string, _maxDepth?: number): Promise<GraphPath[]> {\n // TODO: Implement real graph traversal with JanusGraph\n // For now, return empty array\n return [];\n }\n \n async getEntityTypeStats(): Promise<EntityTypeStats[]> {\n const docs = await this.g!.V().hasLabel('Resource').toList();\n const resources = docs.map((v: any) => this.vertexToResource(v));\n\n const stats = new Map<string, number>();\n\n for (const doc of resources) {\n for (const type of doc.entityTypes || []) {\n stats.set(type, (stats.get(type) || 0) + 1);\n }\n }\n\n return Array.from(stats.entries()).map(([type, count]) => ({ type, count }));\n }\n \n async getStats(): Promise<any> {\n const entityTypes: Record<string, number> = {};\n const contentTypes: Record<string, number> = {};\n\n // Get all resources\n const docs = await this.g!.V().hasLabel('Resource').toList();\n const resources = docs.map((v: any) => this.vertexToResource(v));\n\n for (const doc of resources) {\n for (const type of doc.entityTypes || []) {\n entityTypes[type] = (entityTypes[type] || 0) + 1;\n }\n const primaryRep = getPrimaryRepresentation(doc);\n if (primaryRep?.mediaType) {\n contentTypes[primaryRep.mediaType] = (contentTypes[primaryRep.mediaType] || 0) + 1;\n }\n }\n\n // Get all annotations\n const anns = await this.g!.V().hasLabel('Annotation').toList();\n const annotations = await this.fetchAnnotationsWithEntityTypes(anns);\n\n const highlights = annotations.filter(a => a.motivation === 'highlighting');\n const references = annotations.filter(a => a.motivation === 'linking');\n const entityReferences = references.filter(a => getEntityTypes(a).length > 0);\n\n return {\n resourceCount: resources.length,\n annotationCount: annotations.length,\n highlightCount: highlights.length,\n referenceCount: references.length,\n entityReferenceCount: entityReferences.length,\n entityTypes,\n contentTypes,\n };\n }\n\n async batchCreateResources(resources: ResourceDescriptor[]): Promise<ResourceDescriptor[]> {\n const results: ResourceDescriptor[] = [];\n for (const resource of resources) {\n results.push(await this.createResource(resource));\n }\n return results;\n }\n\n async createAnnotations(inputs: CreateAnnotationInternal[]): Promise<Annotation[]> {\n const results = [];\n for (const input of inputs) {\n results.push(await this.createAnnotation(input));\n }\n return results;\n }\n\n async resolveReferences(inputs: Array<{ annotationId: AnnotationId; source: ResourceId }>): Promise<Annotation[]> {\n const results = [];\n for (const input of inputs) {\n results.push(await this.resolveReference(input.annotationId, input.source));\n }\n return results;\n }\n\n async detectAnnotations(_resourceId: ResourceId): Promise<Annotation[]> {\n // Auto-detection would analyze resource content\n return [];\n }\n \n async getEntityTypes(): Promise<string[]> {\n if (this.entityTypesCollection === null) {\n await this.initializeTagCollections();\n }\n return Array.from(this.entityTypesCollection!).sort();\n }\n \n async addEntityType(tag: string): Promise<void> {\n if (this.entityTypesCollection === null) {\n await this.initializeTagCollections();\n }\n this.entityTypesCollection!.add(tag);\n\n // Persist to JanusGraph\n try {\n // Find or create the TagCollection vertex\n const existing = await this.g!.V()\n .hasLabel('TagCollection')\n .has('type', 'entity-types')\n .toList();\n\n if (existing.length > 0) {\n // Update existing collection\n await this.g!.V(existing[0])\n .property('tags', JSON.stringify(Array.from(this.entityTypesCollection!)))\n .next();\n } else {\n // Create new collection\n await this.g!.addV('TagCollection')\n .property('type', 'entity-types')\n .property('tags', JSON.stringify(Array.from(this.entityTypesCollection!)))\n .next();\n }\n } catch (error) {\n this.logger?.error('Failed to add entity type', { error });\n }\n }\n\n async addEntityTypes(tags: string[]): Promise<void> {\n if (this.entityTypesCollection === null) {\n await this.initializeTagCollections();\n }\n tags.forEach(tag => this.entityTypesCollection!.add(tag));\n\n // Persist all at once\n try {\n const existing = await this.g!.V()\n .hasLabel('TagCollection')\n .has('type', 'entity-types')\n .toList();\n\n if (existing.length > 0) {\n await this.g!.V(existing[0])\n .property('tags', JSON.stringify(Array.from(this.entityTypesCollection!)))\n .next();\n } else {\n await this.g!.addV('TagCollection')\n .property('type', 'entity-types')\n .property('tags', JSON.stringify(Array.from(this.entityTypesCollection!)))\n .next();\n }\n } catch (error) {\n this.logger?.error('Failed to add entity types', { error });\n }\n }\n\n private async initializeTagCollections(): Promise<void> {\n // Load existing collections from JanusGraph\n const collections = await this.g!.V()\n .hasLabel('TagCollection')\n .toList();\n\n let entityTypesFromDb: string[] = [];\n\n for (const vertex of collections) {\n const props = (vertex as any).properties || {};\n const type = getPropertyValue(props, 'type');\n const tagsJson = getPropertyValue(props, 'tags');\n const tags = tagsJson ? JSON.parse(tagsJson) : [];\n\n if (type === 'entity-types') {\n entityTypesFromDb = tags;\n }\n }\n\n // Load defaults\n const { DEFAULT_ENTITY_TYPES } = await import('@semiont/ontology');\n\n // Merge with defaults\n this.entityTypesCollection = new Set([...DEFAULT_ENTITY_TYPES, ...entityTypesFromDb]);\n\n // Persist merged collection back to JanusGraph if it doesn't exist\n if (entityTypesFromDb.length === 0) {\n await this.addEntityTypes([]);\n }\n }\n\n generateId(): string {\n return uuidv4().replace(/-/g, '').substring(0, 12);\n }\n \n async clearDatabase(): Promise<void> {\n // Drop all vertices in JanusGraph\n await this.g!.V().drop().next();\n // Reset cached collections\n this.entityTypesCollection = null;\n this.logger?.info('Cleared JanusGraph database');\n }\n}","// In-memory implementation of GraphDatabase interface\n// Used for development and testing without requiring a real graph database\n\nimport { GraphDatabase } from '../interface';\nimport { assertMutableResourceUpdate } from '../interface';\nimport { queryResources } from '../resource-query';\nimport type { Logger } from '@semiont/core';\nimport type {\n AnnotationCategory,\n GraphConnection,\n GraphPath,\n EntityTypeStats,\n ResourceFilter,\n UpdateResourceInput,\n CreateAnnotationInternal,\n ResourceId,\n AnnotationId,\n} from '@semiont/core';\nimport { resourceId as makeResourceId } from '@semiont/core';\nimport { v4 as uuidv4 } from 'uuid';\nimport { getBodySource, getTargetSource, getResourceId, getPrimaryRepresentation, getResourceEntityTypes } from '@semiont/core';\nimport { getEntityTypes } from '@semiont/ontology';\nimport { buildAnnotation, decodeAnnotation, encodeAnnotation } from '../annotation-codec';\nimport type { ResourceDescriptor } from '@semiont/core';\nimport type { Annotation } from '@semiont/core';\n\n// Simple in-memory storage using Maps\n// Useful for development and testing\n\nexport class MemoryGraphDatabase implements GraphDatabase {\n private connected: boolean = false;\n private logger?: Logger;\n\n // In-memory storage using Maps\n private resources: Map<string, ResourceDescriptor> = new Map();\n private annotations: Map<string, Annotation> = new Map();\n\n constructor(config: { logger?: Logger } = {}) {\n this.logger = config.logger;\n }\n \n async connect(): Promise<void> {\n // No actual connection needed for in-memory storage\n this.logger?.info('Using in-memory graph database');\n this.connected = true;\n }\n \n async disconnect(): Promise<void> {\n // Nothing to close for in-memory storage\n this.connected = false;\n }\n \n isConnected(): boolean {\n return this.connected;\n }\n\n async createResource(resource: ResourceDescriptor): Promise<ResourceDescriptor> {\n const id = getResourceId(resource);\n if (!id) {\n throw new Error('Resource must have an id');\n }\n\n // Simply add to in-memory map\n // await this.client.submit(`\n // graph.tx().rollback()\n // g.addV('Resource')\n // .property('id', id)\n // .property('name', name)\n // .property('entityTypes', entityTypes)\n // .property('contentType', contentType)\n // .property('created', created)\n // .property('updatedAt', updatedAt)\n // graph.tx().commit()\n // `, { id, name, entityTypes, ... });\n\n this.resources.set(id, resource);\n return resource;\n }\n \n async getResource(id: ResourceId): Promise<ResourceDescriptor | null> {\n return this.resources.get(String(id)) || null;\n }\n\n async updateResource(id: ResourceId, input: UpdateResourceInput): Promise<ResourceDescriptor> {\n assertMutableResourceUpdate(input);\n\n const doc = this.resources.get(String(id));\n if (!doc) throw new Error('Resource not found');\n\n if (input.archived !== undefined) doc.archived = input.archived;\n if (input.entityTypes !== undefined) doc.entityTypes = input.entityTypes;\n return doc;\n }\n\n async deleteResource(id: ResourceId): Promise<void> {\n this.resources.delete(String(id));\n\n // Delete annotations targeting or referencing this resource\n const idStr = String(id);\n for (const [selId, sel] of this.annotations) {\n if (getTargetSource(sel.target) === idStr || getBodySource(sel.body) === idStr) {\n this.annotations.delete(selId);\n }\n }\n }\n \n async listResources(filter: ResourceFilter): Promise<{ resources: ResourceDescriptor[]; total: number }> {\n return queryResources(Array.from(this.resources.values()), filter);\n }\n\n \n async createAnnotation(input: CreateAnnotationInternal): Promise<Annotation> {\n // The caller's id is the system of record's — never mint a fresh one\n // (the event-log id is what deletes and lookups arrive under).\n const id = input.id;\n\n // Nothing here needs serializing — but this store is the reference the\n // interface-contract suite runs against, and a reference that cannot\n // exhibit what the real stores exhibit is why four codec divergences\n // survived. So the annotation round-trips through the codec: what a Map\n // hands back is exactly what Cypher and Gremlin hand back.\n const annotation = decodeAnnotation(\n encodeAnnotation(buildAnnotation(input, new Date().toISOString())),\n getEntityTypes(input)\n );\n\n this.annotations.set(id, annotation);\n this.logger?.debug('Created annotation', {\n id,\n motivation: annotation.motivation,\n hasSource: !!getBodySource(annotation.body),\n targetSource: getTargetSource(annotation.target)\n });\n return annotation;\n }\n \n async getAnnotation(id: AnnotationId): Promise<Annotation | null> {\n return this.annotations.get(id) || null;\n }\n \n async updateAnnotation(id: AnnotationId, updates: Partial<Annotation>): Promise<Annotation> {\n const annotation = this.annotations.get(id);\n if (!annotation) throw new Error('Annotation not found');\n\n const updated: Annotation = {\n ...annotation,\n ...updates,\n };\n\n // Motivation should come from updates if provided\n // No need to derive from body type\n\n this.annotations.set(id, updated);\n return updated;\n }\n \n async deleteAnnotation(id: AnnotationId): Promise<void> {\n this.annotations.delete(id);\n }\n \n async listAnnotations(filter: { resourceId?: ResourceId; type?: AnnotationCategory }): Promise<{ annotations: Annotation[]; total: number }> {\n let results = Array.from(this.annotations.values());\n\n if (filter.resourceId) {\n const resourceIdStr = String(filter.resourceId);\n results = results.filter(a => getTargetSource(a.target) === resourceIdStr);\n }\n\n // Only SpecificResource supported, use motivation to distinguish\n if (filter.type) {\n const motivation = filter.type === 'highlight' ? 'highlighting' : 'linking';\n results = results.filter(a => a.motivation === motivation);\n }\n\n return { annotations: results, total: results.length };\n }\n\n async getHighlights(resourceId: ResourceId): Promise<Annotation[]> {\n const resourceIdStr = String(resourceId);\n const highlights = Array.from(this.annotations.values())\n .filter(sel => getTargetSource(sel.target) === resourceIdStr && sel.motivation === 'highlighting');\n this.logger?.debug('Got highlights for resource', { resourceId, count: highlights.length });\n return highlights;\n }\n\n async resolveReference(annotationId: AnnotationId, source: ResourceId): Promise<Annotation> {\n const annotation = this.annotations.get(annotationId);\n if (!annotation) throw new Error('Annotation not found');\n\n // Convert stub (empty array) to resolved SpecificResource\n const updated: Annotation = {\n ...annotation,\n body: {\n type: 'SpecificResource',\n source: String(source),\n purpose: 'linking',\n },\n };\n\n this.annotations.set(annotationId, updated);\n return updated;\n }\n\n async getReferences(resourceId: ResourceId): Promise<Annotation[]> {\n const resourceIdStr = String(resourceId);\n const references = Array.from(this.annotations.values())\n .filter(sel => getTargetSource(sel.target) === resourceIdStr && sel.motivation === 'linking');\n this.logger?.debug('Got references for resource', { resourceId, count: references.length });\n return references;\n }\n\n async getEntityReferences(resourceId: ResourceId, entityTypes?: string[]): Promise<Annotation[]> {\n const resourceIdStr = String(resourceId);\n let refs = Array.from(this.annotations.values())\n .filter(sel => getTargetSource(sel.target) === resourceIdStr && getEntityTypes(sel).length > 0);\n\n if (entityTypes && entityTypes.length > 0) {\n refs = refs.filter(sel => getEntityTypes(sel).some(type => entityTypes.includes(type)));\n }\n\n return refs;\n }\n\n async getResourceAnnotations(resourceId: ResourceId): Promise<Annotation[]> {\n const resourceIdStr = String(resourceId);\n return Array.from(this.annotations.values())\n .filter(sel => getTargetSource(sel.target) === resourceIdStr);\n }\n\n async getResourceReferencedBy(resourceId: ResourceId, _motivation?: string): Promise<Annotation[]> {\n return Array.from(this.annotations.values())\n .filter(sel => getBodySource(sel.body) === String(resourceId));\n }\n\n async getResourceConnections(resourceId: ResourceId): Promise<GraphConnection[]> {\n const connections: GraphConnection[] = [];\n const refs = await this.getReferences(resourceId);\n const resourceIdStr = String(resourceId);\n\n for (const ref of refs) {\n const bodySource = getBodySource(ref.body);\n if (bodySource) {\n const targetDoc = await this.getResource(makeResourceId(bodySource));\n if (targetDoc) {\n const reverseRefs = await this.getReferences(makeResourceId(bodySource));\n const bidirectional = reverseRefs.some(r => getBodySource(r.body) === resourceIdStr);\n\n connections.push({\n targetResource: targetDoc,\n annotations: [ref],\n bidirectional,\n });\n }\n }\n }\n\n return connections;\n }\n\n async findPath(fromResourceId: string, toResourceId: string, maxDepth: number = 5): Promise<GraphPath[]> {\n const visited = new Set<string>();\n const queue: { docId: string; path: ResourceDescriptor[]; sels: Annotation[] }[] = [];\n const fromDoc = await this.getResource(makeResourceId(fromResourceId));\n\n if (!fromDoc) return [];\n\n queue.push({ docId: fromResourceId, path: [fromDoc], sels: [] });\n visited.add(fromResourceId);\n\n const paths: GraphPath[] = [];\n\n while (queue.length > 0 && paths.length < 10) {\n const { docId, path, sels } = queue.shift()!;\n\n if (path.length > maxDepth) continue;\n\n if (docId === toResourceId) {\n paths.push({ resources: path, annotations: sels });\n continue;\n }\n\n const connections = await this.getResourceConnections(makeResourceId(docId));\n\n for (const conn of connections) {\n const targetId = getResourceId(conn.targetResource);\n if (targetId && !visited.has(targetId)) {\n visited.add(targetId);\n queue.push({\n docId: targetId,\n path: [...path, conn.targetResource],\n sels: [...sels, ...conn.annotations],\n });\n }\n }\n }\n\n return paths;\n }\n \n async getEntityTypeStats(): Promise<EntityTypeStats[]> {\n // Simple in-memory statistics\n // const results = await this.client.submit(`\n // g.V().hasLabel('Resource')\n // .values('entityTypes').unfold()\n // .groupCount()\n // `);\n\n const typeCounts = new Map<string, number>();\n\n for (const doc of this.resources.values()) {\n const types = getResourceEntityTypes(doc);\n for (const type of types) {\n typeCounts.set(type, (typeCounts.get(type) || 0) + 1);\n }\n }\n \n return Array.from(typeCounts.entries()).map(([type, count]) => ({\n type,\n count,\n }));\n }\n \n async getStats(): Promise<{\n resourceCount: number;\n annotationCount: number;\n highlightCount: number;\n referenceCount: number;\n entityReferenceCount: number;\n entityTypes: Record<string, number>;\n contentTypes: Record<string, number>;\n }> {\n const entityTypes: Record<string, number> = {};\n const contentTypes: Record<string, number> = {};\n\n for (const doc of this.resources.values()) {\n for (const type of doc.entityTypes || []) {\n entityTypes[type] = (entityTypes[type] || 0) + 1;\n }\n const primaryRep = getPrimaryRepresentation(doc);\n if (primaryRep?.mediaType) {\n contentTypes[primaryRep.mediaType] = (contentTypes[primaryRep.mediaType] || 0) + 1;\n }\n }\n \n const annotations = Array.from(this.annotations.values());\n // Use motivation to distinguish types\n const highlightCount = annotations.filter(a => a.motivation === 'highlighting').length;\n const referenceCount = annotations.filter(a => a.motivation === 'linking').length;\n // Extract entity types from annotation body\n const entityReferenceCount = annotations.filter(\n a => a.motivation === 'linking' && getEntityTypes(a).length > 0\n ).length;\n \n return {\n resourceCount: this.resources.size,\n annotationCount: this.annotations.size,\n highlightCount,\n referenceCount,\n entityReferenceCount,\n entityTypes,\n contentTypes,\n };\n }\n \n async batchCreateResources(resources: ResourceDescriptor[]): Promise<ResourceDescriptor[]> {\n const results: ResourceDescriptor[] = [];\n for (const resource of resources) {\n results.push(await this.createResource(resource));\n }\n return results;\n }\n\n async createAnnotations(inputs: CreateAnnotationInternal[]): Promise<Annotation[]> {\n const results: Annotation[] = [];\n for (const input of inputs) {\n results.push(await this.createAnnotation(input));\n }\n return results;\n }\n \n \n async resolveReferences(inputs: { annotationId: AnnotationId; source: ResourceId }[]): Promise<Annotation[]> {\n const results: Annotation[] = [];\n for (const input of inputs) {\n results.push(await this.resolveReference(input.annotationId, input.source));\n }\n return results;\n }\n \n async detectAnnotations(_resourceId: ResourceId): Promise<Annotation[]> {\n // This would use AI/ML to detect annotations in a resource\n // For now, return empty array as a placeholder\n return [];\n }\n \n // Tag Collections - stored as special vertices in the graph\n private entityTypesCollection: Set<string> | null = null;\n \n async getEntityTypes(): Promise<string[]> {\n // Initialize if not already loaded\n if (this.entityTypesCollection === null) {\n await this.initializeTagCollections();\n }\n return Array.from(this.entityTypesCollection!).sort();\n }\n\n async addEntityType(tag: string): Promise<void> {\n if (this.entityTypesCollection === null) {\n await this.initializeTagCollections();\n }\n this.entityTypesCollection!.add(tag);\n // Simply add to set\n // await this.client.submit(`g.V().has('tagCollection', 'type', 'entity-types')\n // .property(set, 'tags', '${tag}')`, {});\n }\n\n async addEntityTypes(tags: string[]): Promise<void> {\n if (this.entityTypesCollection === null) {\n await this.initializeTagCollections();\n }\n tags.forEach(tag => this.entityTypesCollection!.add(tag));\n // Simply add to set\n }\n \n private async initializeTagCollections(): Promise<void> {\n // Initialize in-memory collections\n // const result = await this.client.submit(\n // `g.V().has('tagCollection', 'type', 'entity-types')\n // .project('type', 'tags').by('type').by('tags')`, {}\n // );\n\n // For now, initialize with defaults if not present\n if (this.entityTypesCollection === null) {\n const { DEFAULT_ENTITY_TYPES } = await import('@semiont/ontology');\n this.entityTypesCollection = new Set(DEFAULT_ENTITY_TYPES);\n }\n }\n \n generateId(): string {\n return uuidv4().replace(/-/g, '').substring(0, 12);\n }\n \n async clearDatabase(): Promise<void> {\n // In production: CAREFUL! This would clear the entire graph\n // await this.client.submit(`g.V().drop()`);\n this.resources.clear();\n this.annotations.clear();\n this.entityTypesCollection = null;\n }\n}","// Factory for creating graph database instances based on configuration\n\nimport { GraphDatabase } from './interface';\nimport { NeptuneGraphDatabase } from './implementations/neptune';\nimport { Neo4jGraphDatabase } from './implementations/neo4j';\nimport { JanusGraphDatabase } from './implementations/janusgraph';\nimport { MemoryGraphDatabase } from './implementations/memorygraph';\nimport type { GraphServiceConfig } from '@semiont/core';\n\nexport type GraphDatabaseType = 'neptune' | 'neo4j' | 'janusgraph' | 'memory';\n\nexport interface GraphDatabaseConfig {\n type: GraphDatabaseType;\n\n // Neptune config\n neptuneEndpoint?: string;\n neptunePort?: number;\n neptuneRegion?: string;\n\n // Neo4j config\n neo4jUri?: string;\n neo4jUsername?: string;\n neo4jPassword?: string;\n neo4jDatabase?: string;\n\n // JanusGraph config\n janusHost?: string;\n janusPort?: number;\n janusStorageBackend?: 'cassandra' | 'hbase' | 'berkeleydb';\n janusIndexBackend?: 'elasticsearch' | 'solr' | 'lucene';\n}\n\n// Singleton instance\nlet graphDatabaseInstance: GraphDatabase | null = null;\n\nexport function createGraphDatabase(config: GraphDatabaseConfig): GraphDatabase {\n switch (config.type) {\n case 'neptune': {\n const neptuneConfig: any = {};\n if (config.neptuneEndpoint !== undefined) neptuneConfig.endpoint = config.neptuneEndpoint;\n if (config.neptunePort !== undefined) neptuneConfig.port = config.neptunePort;\n if (config.neptuneRegion !== undefined) neptuneConfig.region = config.neptuneRegion;\n return new NeptuneGraphDatabase(neptuneConfig);\n }\n\n case 'neo4j': {\n const neo4jConfig: any = {};\n if (config.neo4jUri !== undefined) neo4jConfig.uri = config.neo4jUri;\n if (config.neo4jUsername !== undefined) neo4jConfig.username = config.neo4jUsername;\n if (config.neo4jPassword !== undefined) neo4jConfig.password = config.neo4jPassword;\n if (config.neo4jDatabase !== undefined) neo4jConfig.database = config.neo4jDatabase;\n return new Neo4jGraphDatabase(neo4jConfig);\n }\n\n case 'janusgraph': {\n const janusConfig: any = {};\n if (config.janusHost !== undefined) janusConfig.host = config.janusHost;\n if (config.janusPort !== undefined) janusConfig.port = config.janusPort;\n if (config.janusStorageBackend !== undefined) janusConfig.storageBackend = config.janusStorageBackend;\n if (config.janusIndexBackend !== undefined) janusConfig.indexBackend = config.janusIndexBackend;\n return new JanusGraphDatabase(janusConfig);\n }\n\n case 'memory':\n // Hermetic TEST sink only (WEAVER-ISOLATION D4 refinement): a heap-\n // local graph cannot be shared with a standalone Weaver, so no\n // deployment configures it — and none does. weaver-main refuses it.\n return new MemoryGraphDatabase({});\n\n default:\n throw new Error(`Unsupported graph database type: ${config.type}`);\n }\n}\n\n// Helper function to evaluate environment variable placeholders\nfunction evaluateEnvVar(value: string | undefined): string | undefined {\n if (!value) return undefined;\n\n // Replace ${VAR_NAME} with actual environment variable value\n return value.replace(/\\$\\{([^}]+)\\}/g, (match, varName) => {\n const envValue = process.env[varName];\n if (!envValue) {\n throw new Error(`Environment variable ${varName} is not set. Referenced in configuration as ${match}`);\n }\n return envValue;\n });\n}\n\nexport async function getGraphDatabase(graphConfig: GraphServiceConfig): Promise<GraphDatabase> {\n if (!graphDatabaseInstance) {\n const config: GraphDatabaseConfig = {\n type: graphConfig.type,\n };\n\n // Apply configuration based on type\n if (graphConfig.type === 'janusgraph') {\n if (graphConfig.host) {\n config.janusHost = graphConfig.host;\n }\n if (graphConfig.port) {\n config.janusPort = graphConfig.port;\n }\n if (graphConfig.storage) {\n config.janusStorageBackend = graphConfig.storage as any;\n }\n if (graphConfig.index && graphConfig.index !== 'none') {\n config.janusIndexBackend = graphConfig.index as any;\n }\n } else if (graphConfig.type === 'neptune') {\n if (graphConfig.endpoint) {\n config.neptuneEndpoint = graphConfig.endpoint;\n }\n if (graphConfig.port) {\n config.neptunePort = graphConfig.port;\n }\n if (graphConfig.region) {\n config.neptuneRegion = graphConfig.region;\n }\n } else if (graphConfig.type === 'neo4j') {\n if (graphConfig.uri) {\n config.neo4jUri = evaluateEnvVar(graphConfig.uri);\n }\n if (graphConfig.username) {\n config.neo4jUsername = evaluateEnvVar(graphConfig.username);\n }\n if (graphConfig.password) {\n config.neo4jPassword = evaluateEnvVar(graphConfig.password);\n }\n if (graphConfig.database) {\n config.neo4jDatabase = evaluateEnvVar(graphConfig.database);\n }\n }\n\n graphDatabaseInstance = createGraphDatabase(config);\n await graphDatabaseInstance.connect();\n }\n\n if (!graphDatabaseInstance.isConnected()) {\n await graphDatabaseInstance.connect();\n }\n\n return graphDatabaseInstance;\n}\n\nexport async function closeGraphDatabase(): Promise<void> {\n if (graphDatabaseInstance) {\n await graphDatabaseInstance.disconnect();\n graphDatabaseInstance = null;\n }\n}"],"mappings":"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","names":["getBodySource","getTargetSource","getStorageUri","process","entityTypes","targetDocId","uuidv4","getPrimaryRepresentation","getStorageUri","getEntityTypes","getPrimaryRepresentation","getStorageUri","getEntityTypes","uuidv4","normalizeProperties","getBodySource","getPrimaryRepresentation","getResourceId","getStorageUri","getEntityTypes","uuidv4","vertexToAnnotation","gremlin","getResourceId","getPrimaryRepresentation","getStorageUri","getEntityTypes","getBodySource","uuidv4","makeResourceId","uuidv4","getBodySource","getTargetSource","getResourceId","getPrimaryRepresentation","getResourceEntityTypes","getEntityTypes","getResourceId","getTargetSource","getBodySource","getEntityTypes","makeResourceId","getResourceEntityTypes","getPrimaryRepresentation","uuidv4"]}
|
|
1
|
+
{"version":3,"sources":["../src/interface.ts","../src/resource-query.ts","../src/implementations/neptune.ts","../src/annotation-codec.ts","../src/implementations/neo4j.ts","../src/implementations/janusgraph.ts","../src/implementations/memorygraph.ts","../src/factory.ts"],"sourcesContent":["// Graph database interface - all implementations must follow this contract\n\nimport type {\n Annotation,\n AnnotationCategory,\n AnnotationId,\n CreateAnnotationInternal,\n EntityTypeStats,\n GraphConnection,\n GraphPath,\n ResourceDescriptor,\n ResourceFilter,\n ResourceId,\n UpdateResourceInput,\n} from '@semiont/core';\n\nconst MUTABLE_RESOURCE_FACETS = new Set<string>(['archived', 'entityTypes']);\n\n/**\n * Resources are immutable apart from two facets: archival state, and entity\n * tags (mutable since the controlled-vocabulary decision — the Weaver folds\n * `mark:archived`/`mark:unarchived` and `mark:entity-tag-added`/`-removed`\n * through `updateResource`). Every implementation validates its input with\n * this one guard so the mutability contract cannot drift per gateway.\n */\nexport function assertMutableResourceUpdate(input: UpdateResourceInput): void {\n const keys = Object.keys(input);\n if (keys.length === 0 || keys.some((k) => !MUTABLE_RESOURCE_FACETS.has(k))) {\n throw new Error('Resources are immutable apart from archival state and entity tags.');\n }\n}\n\n/**\n * Newest first, ties broken by id — the ordering every `listResources` result\n * must carry.\n *\n * The tiebreak is not cosmetic: browse pages these results with offset/limit,\n * and a partial order lets two pages repeat or drop rows. Ids compare by code\n * point rather than locale so the JS gateways agree with the engines, whose\n * `ORDER BY` is codepoint-ordered.\n */\nexport function compareByRecencyThenId(a: ResourceDescriptor, b: ResourceDescriptor): number {\n const aTime = a.dateCreated ? Date.parse(a.dateCreated) : 0;\n const bTime = b.dateCreated ? Date.parse(b.dateCreated) : 0;\n if (aTime !== bTime) return bTime - aTime;\n const aId = String(a['@id']);\n const bId = String(b['@id']);\n return aId < bId ? -1 : aId > bId ? 1 : 0;\n}\n\nexport interface GraphDatabase {\n // Connection management\n connect(): Promise<void>;\n disconnect(): Promise<void>;\n isConnected(): boolean;\n\n // Resource operations\n // Accepts W3C ResourceDescriptor directly - GraphDB stores W3C compliant resources\n createResource(resource: ResourceDescriptor): Promise<ResourceDescriptor>;\n getResource(id: ResourceId): Promise<ResourceDescriptor | null>;\n updateResource(id: ResourceId, input: UpdateResourceInput): Promise<ResourceDescriptor>;\n deleteResource(id: ResourceId): Promise<void>;\n listResources(filter: ResourceFilter): Promise<{ resources: ResourceDescriptor[]; total: number }>;\n\n // Annotation operations\n createAnnotation(input: CreateAnnotationInternal): Promise<Annotation>;\n getAnnotation(id: AnnotationId): Promise<Annotation | null>;\n updateAnnotation(id: AnnotationId, updates: Partial<Annotation>): Promise<Annotation>;\n deleteAnnotation(id: AnnotationId): Promise<void>;\n listAnnotations(filter: { resourceId?: ResourceId; type?: AnnotationCategory }): Promise<{ annotations: Annotation[]; total: number }>;\n\n // Highlight operations\n getHighlights(resourceId: ResourceId): Promise<Annotation[]>;\n\n // Reference operations\n resolveReference(annotationId: AnnotationId, source: ResourceId): Promise<Annotation>;\n getReferences(resourceId: ResourceId): Promise<Annotation[]>;\n getEntityReferences(resourceId: ResourceId, entityTypes?: string[]): Promise<Annotation[]>;\n\n // Relationship queries\n getResourceAnnotations(resourceId: ResourceId): Promise<Annotation[]>;\n getResourceReferencedBy(resourceId: ResourceId, motivation?: string): Promise<Annotation[]>;\n\n // Graph traversal\n getResourceConnections(resourceId: ResourceId): Promise<GraphConnection[]>;\n findPath(fromResourceId: ResourceId, toResourceId: ResourceId, maxDepth?: number): Promise<GraphPath[]>;\n \n // Analytics\n getEntityTypeStats(): Promise<EntityTypeStats[]>;\n getStats(): Promise<{\n resourceCount: number;\n annotationCount: number;\n highlightCount: number;\n referenceCount: number;\n entityReferenceCount: number;\n entityTypes: Record<string, number>;\n contentTypes: Record<string, number>;\n }>;\n \n // Bulk operations\n batchCreateResources(resources: ResourceDescriptor[]): Promise<ResourceDescriptor[]>;\n createAnnotations(inputs: CreateAnnotationInternal[]): Promise<Annotation[]>;\n resolveReferences(inputs: { annotationId: AnnotationId; source: ResourceId }[]): Promise<Annotation[]>;\n\n // Auto-detection\n detectAnnotations(resourceId: ResourceId): Promise<Annotation[]>;\n \n // Tag Collections\n getEntityTypes(): Promise<string[]>;\n addEntityType(tag: string): Promise<void>;\n addEntityTypes(tags: string[]): Promise<void>;\n \n // Utility\n generateId(): string;\n clearDatabase(): Promise<void>; // For testing\n}","/**\n * The resource query — filtering, ranking and pagination — expressed in JS.\n *\n * Shared by every gateway whose engine does not express it directly (memory,\n * JanusGraph, Neptune) so those three cannot drift apart. Neo4j expresses the\n * same semantics in Cypher, and the interface contract tests pin both shapes to\n * one behaviour.\n */\n\nimport { getResourceEntityTypes, getStorageUri } from '@semiont/core';\nimport type { ResourceDescriptor, ResourceFilter } from '@semiont/core';\nimport { compareByRecencyThenId } from './interface';\n\n/**\n * Split a query into the terms every match must satisfy. Blank input yields no\n * terms, which callers read as \"no query\" — a bare substring match on `\" \"`\n * would otherwise match every name containing a space.\n */\nexport function searchTerms(query: string): string[] {\n return query.toLowerCase().split(/\\s+/).filter(Boolean);\n}\n\n/**\n * How directly a resource answers the query: 0 exact name, 1 name prefix,\n * 2 every term present in the name, 3 something other than the name — the path\n * or an entity type — had to supply a term.\n *\n * Those assisted hits rank last deliberately. Someone searching \"Marathon\"\n * wants the document *called* Marathon before every file that merely lives\n * under a folder of that name or is tagged with it.\n */\nexport function searchRank(resource: ResourceDescriptor, query: string): number {\n const whole = query.trim().toLowerCase();\n const name = (resource.name ?? '').toLowerCase();\n if (name === whole) return 0;\n if (name.startsWith(whole)) return 1;\n if (searchTerms(query).every((term) => name.includes(term))) return 2;\n return 3;\n}\n\n/**\n * Every term must appear, though each may come from the name, the path or an\n * entity type — so \"Aeschylus Marathon\" finds a resource named for one and\n * filed under the other, and \"Historian\" finds what is tagged as one.\n */\nfunction matchesSearch(resource: ResourceDescriptor, terms: string[]): boolean {\n const name = (resource.name ?? '').toLowerCase();\n const uri = getStorageUri(resource)?.toLowerCase() ?? '';\n const types = getResourceEntityTypes(resource).map((t) => t.toLowerCase());\n return terms.every((term) =>\n name.includes(term) || uri.includes(term) || types.some((t) => t.includes(term)));\n}\n\n/**\n * Filter, order and page a resource set. Filters always run before pagination,\n * so `total` describes the match set rather than the page.\n */\nexport function queryResources(\n all: ResourceDescriptor[],\n filter: ResourceFilter,\n): { resources: ResourceDescriptor[]; total: number } {\n let matches = all;\n\n if (filter.entityTypes && filter.entityTypes.length > 0) {\n matches = matches.filter((doc) =>\n filter.entityTypes!.some((type) => getResourceEntityTypes(doc).includes(type)));\n }\n\n // A query of only whitespace has no terms, and so filters nothing.\n const terms = filter.search ? searchTerms(filter.search) : [];\n if (terms.length > 0) {\n matches = matches.filter((doc) => matchesSearch(doc, terms));\n }\n\n if (filter.archived !== undefined) {\n matches = matches.filter((doc) => (doc.archived ?? false) === filter.archived);\n }\n\n const search = terms.length > 0 ? filter.search! : undefined;\n const ordered = [...matches].sort(\n search\n ? (a, b) => (searchRank(a, search) - searchRank(b, search)) || compareByRecencyThenId(a, b)\n : compareByRecencyThenId,\n );\n\n const offset = filter.offset ?? 0;\n const limit = filter.limit ?? 20;\n return { resources: ordered.slice(offset, offset + limit), total: ordered.length };\n}\n","// AWS Neptune implementation of GraphDatabase interface\n// Uses Gremlin for graph traversal\n\nimport { GraphDatabase } from '../interface';\nimport { assertMutableResourceUpdate } from '../interface';\nimport { queryResources } from '../resource-query';\nimport { getEntityTypes } from '@semiont/ontology';\nimport type { Logger } from '@semiont/core';\nimport {\n buildAnnotation,\n decodeAnnotation,\n encodeAnnotation,\n encodeSelector,\n motivationForCategory,\n storedAnnotationType,\n type AnnotationProperties,\n} from '../annotation-codec';\nimport type {\n AnnotationCategory,\n GraphConnection,\n GraphPath,\n EntityTypeStats,\n ResourceFilter,\n UpdateResourceInput,\n CreateAnnotationInternal,\n ResourceId,\n AnnotationId,\n} from '@semiont/core';\nimport { v4 as uuidv4 } from 'uuid';\nimport { getBodySource, getTargetSource, getPrimaryRepresentation, getResourceId, getStorageUri } from '@semiont/core';\nimport type { ResourceDescriptor } from '@semiont/core';\nimport type { Annotation } from '@semiont/core';\n\n// Dynamic imports for AWS SDK and Gremlin\nlet NeptuneClient: any;\nlet DescribeDBClustersCommand: any;\nlet gremlin: any;\nlet process: any;\nlet TextP: any;\nlet cardinality: any;\nlet __: any;\n\nasync function loadDependencies() {\n if (!NeptuneClient) {\n const neptuneModule = await import('@aws-sdk/client-neptune');\n NeptuneClient = neptuneModule.NeptuneClient;\n DescribeDBClustersCommand = neptuneModule.DescribeDBClustersCommand;\n }\n if (!gremlin) {\n // @ts-ignore - gremlin module has no types\n gremlin = await import('gremlin');\n process = gremlin.process;\n TextP = process.TextP;\n cardinality = process.cardinality;\n __ = process.statics;\n }\n}\n\n// Helper function to convert Neptune vertex to ResourceDescriptor\nfunction vertexToResource(vertex: any): ResourceDescriptor {\n const props = vertex.properties || vertex;\n\n // Handle different property formats from Neptune\n const getValue = (key: string, required: boolean = false) => {\n const prop = props[key];\n if (!prop) {\n if (required) {\n throw new Error(`Resource ${vertex.id || 'unknown'} missing required field: ${key}`);\n }\n return undefined;\n }\n if (Array.isArray(prop) && prop.length > 0) {\n return prop[0].value !== undefined ? prop[0].value : prop[0];\n }\n return prop.value !== undefined ? prop.value : prop;\n };\n\n // Get all required fields and validate\n const id = getValue('id', true);\n const name = getValue('name', true);\n const entityTypesRaw = getValue('entityTypes', true);\n const mediaType = getValue('mediaType', true);\n const archived = getValue('archived', true);\n const dateCreated = getValue('dateCreated', true);\n const checksum = getValue('checksum', true);\n const creatorRaw = getValue('creator', true);\n\n const resource: ResourceDescriptor = {\n '@context': 'https://schema.org/',\n '@id': id,\n name,\n entityTypes: JSON.parse(entityTypesRaw),\n representations: [{\n mediaType,\n checksum,\n rel: 'original',\n storageUri: getValue('storageUri') || undefined,\n }],\n archived: archived === 'true' || archived === true,\n dateCreated,\n wasAttributedTo: typeof creatorRaw === 'string' ? JSON.parse(creatorRaw) : creatorRaw,\n };\n\n const sourceResourceId = getValue('sourceResourceId');\n if (sourceResourceId) resource.sourceResourceId = sourceResourceId;\n\n return resource;\n}\n\n/**\n * Convert a Neptune vertex to an Annotation.\n *\n * Exported so the cross-store conformance suite can run this store's decode\n * path with no live Neptune: everything past the flattening below is the\n * shared codec's.\n */\nexport function vertexToAnnotation(vertex: any, entityTypes: string[] = []): Annotation {\n return decodeAnnotation(normalizeProperties(vertex.properties || vertex), entityTypes);\n}\n\n/** Neptune returns each property in one of several shapes depending on the traversal. */\nfunction normalizeProperties(props: any): AnnotationProperties {\n const normalized: AnnotationProperties = {};\n for (const [key, raw] of Object.entries(props ?? {})) {\n const value = unwrap(raw);\n if (value === undefined || value === null) continue;\n normalized[key] = typeof value === 'string' ? value : String(value);\n }\n return normalized;\n}\n\nfunction unwrap(prop: any): any {\n if (prop === undefined || prop === null) return undefined;\n if (Array.isArray(prop)) return prop.length > 0 ? unwrap(prop[0]) : undefined;\n if (typeof prop === 'object' && 'value' in prop) return prop.value;\n return prop;\n}\n\n\nexport class NeptuneGraphDatabase implements GraphDatabase {\n private connected: boolean = false;\n private neptuneEndpoint?: string;\n private neptunePort: number = 8182;\n private region?: string;\n private logger?: Logger;\n private g: any; // Gremlin graph traversal source\n private connection: any; // Gremlin connection\n\n // Helper method to fetch annotations with their entity types\n private async fetchAnnotationsWithEntityTypes(annotationVertices: any[]): Promise<Annotation[]> {\n const annotations: Annotation[] = [];\n\n for (const vertex of annotationVertices) {\n const id = vertex.properties?.id?.[0]?.value || vertex.id;\n\n // Fetch entity types for this annotation\n const entityTypesResult = await this.g.V()\n .hasLabel('Annotation')\n .has('id', id)\n .out('TAGGED_AS')\n .hasLabel('EntityType')\n .values('name')\n .toList();\n\n const entityTypes = entityTypesResult || [];\n annotations.push(vertexToAnnotation(vertex, entityTypes));\n }\n\n return annotations;\n }\n\n constructor(config: {\n endpoint?: string;\n port?: number;\n region?: string;\n logger?: Logger;\n } = {}) {\n if (config.endpoint) this.neptuneEndpoint = config.endpoint;\n this.neptunePort = config.port || 8182;\n if (config.region) this.region = config.region;\n this.logger = config.logger;\n }\n \n private async discoverNeptuneEndpoint(): Promise<void> {\n // If endpoint is already provided, use it\n if (this.neptuneEndpoint) {\n return;\n }\n \n // In AWS environment, discover Neptune cluster endpoint\n if (!this.region) {\n throw new Error('AWS region must be configured in environment JSON file (aws.region) for Neptune endpoint discovery');\n }\n\n try {\n // Load AWS SDK dynamically\n await loadDependencies();\n \n // Create Neptune client\n const client = new NeptuneClient({ region: this.region });\n \n // List all Neptune clusters\n const command = new DescribeDBClustersCommand({});\n const response = await client.send(command);\n \n if (!response.DBClusters || response.DBClusters.length === 0) {\n throw new Error('No Neptune clusters found in region ' + this.region);\n }\n \n // Find the Semiont cluster by tags\n let cluster = null;\n for (const dbCluster of response.DBClusters) {\n // Check if this cluster has our application tag\n const tagsCommand = new DescribeDBClustersCommand({\n DBClusterIdentifier: dbCluster.DBClusterIdentifier\n });\n const clusterDetails = await client.send(tagsCommand);\n \n if (clusterDetails.DBClusters && clusterDetails.DBClusters[0]) {\n const clusterInfo = clusterDetails.DBClusters[0];\n // Check for Semiont tag or name pattern\n if (clusterInfo.DBClusterIdentifier?.includes('Semiont') || \n clusterInfo.DBClusterIdentifier?.includes('semiont')) {\n cluster = clusterInfo;\n break;\n }\n }\n }\n \n if (!cluster) {\n throw new Error('No Semiont Neptune cluster found in region ' + this.region);\n }\n \n // Set the endpoint and port\n this.neptuneEndpoint = cluster.Endpoint;\n this.neptunePort = cluster.Port || 8182;\n\n this.logger?.info('Discovered Neptune endpoint', { endpoint: this.neptuneEndpoint, port: this.neptunePort });\n } catch (error: any) {\n this.logger?.error('Failed to discover Neptune endpoint', { error });\n throw error;\n }\n }\n \n async connect(): Promise<void> {\n // Discover Neptune endpoint if needed\n await this.discoverNeptuneEndpoint();\n \n try {\n // Load Gremlin dynamically\n await loadDependencies();\n \n // Create Gremlin connection\n const traversal = gremlin.process.AnonymousTraversalSource.traversal;\n const DriverRemoteConnection = gremlin.driver.DriverRemoteConnection;\n \n // Neptune requires WebSocket Secure (wss) protocol\n const connectionUrl = `wss://${this.neptuneEndpoint}:${this.neptunePort}/gremlin`;\n this.logger?.info('Connecting to Neptune', { connectionUrl });\n\n // Create the connection\n this.connection = new DriverRemoteConnection(connectionUrl, {\n authenticator: null, // Neptune uses IAM authentication via task role\n rejectUnauthorized: true,\n traversalSource: 'g'\n });\n\n // Create the graph traversal source\n this.g = traversal().withRemote(this.connection);\n\n // Test the connection\n const count = await this.g.V().limit(1).count().next();\n this.logger?.info('Connected to Neptune', { vertexCountTest: count.value });\n\n this.connected = true;\n } catch (error: any) {\n this.logger?.error('Failed to connect to Neptune', { error });\n throw error;\n }\n }\n \n async disconnect(): Promise<void> {\n // Close Gremlin connection if it exists\n if (this.connection) {\n try {\n await this.connection.close();\n } catch (error) {\n this.logger?.error('Error closing Neptune connection', { error });\n }\n }\n\n this.connected = false;\n this.logger?.info('Disconnected from Neptune');\n }\n \n isConnected(): boolean {\n return this.connected;\n }\n\n async createResource(resource: ResourceDescriptor): Promise<ResourceDescriptor> {\n const id = getResourceId(resource);\n const primaryRep = getPrimaryRepresentation(resource);\n if (!primaryRep) {\n throw new Error('Resource must have at least one representation');\n }\n\n // Create vertex in Neptune\n try {\n const vertex = this.g.addV('Resource')\n .property('id', id)\n .property('name', resource.name)\n .property('mediaType', primaryRep.mediaType)\n .property('archived', resource.archived || false)\n .property('dateCreated', resource.dateCreated)\n .property('creator', JSON.stringify(resource.wasAttributedTo))\n .property('checksum', primaryRep.checksum)\n .property('entityTypes', JSON.stringify(resource.entityTypes));\n\n if (resource.sourceResourceId) {\n vertex.property('sourceResourceId', resource.sourceResourceId);\n }\n const storageUri = getStorageUri(resource);\n if (storageUri) {\n vertex.property('storageUri', storageUri);\n }\n\n await vertex.next();\n\n this.logger?.info('Created resource vertex in Neptune', { id });\n return resource;\n } catch (error) {\n this.logger?.error('Failed to create resource in Neptune', { error });\n throw error;\n }\n }\n \n async getResource(id: ResourceId): Promise<ResourceDescriptor | null> {\n try {\n const result = await this.g.V()\n .hasLabel('Resource')\n .has('id', id)\n .elementMap()\n .next();\n \n if (!result.value) {\n return null;\n }\n \n return vertexToResource(result.value);\n } catch (error) {\n this.logger?.error('Failed to get resource from Neptune', { error });\n throw error;\n }\n }\n \n async updateResource(id: ResourceId, input: UpdateResourceInput): Promise<ResourceDescriptor> {\n assertMutableResourceUpdate(input);\n\n try {\n let traversal = this.g.V()\n .hasLabel('Resource')\n .has('id', id);\n if (input.archived !== undefined) {\n traversal = traversal.property('archived', input.archived);\n }\n if (input.entityTypes !== undefined) {\n // Mirrors createResource's storage idiom: entityTypes ride as JSON.\n traversal = traversal.property('entityTypes', JSON.stringify(input.entityTypes));\n }\n const result = await traversal\n .elementMap()\n .next();\n\n if (!result.value) {\n throw new Error('Resource not found');\n }\n\n return vertexToResource(result.value);\n } catch (error) {\n this.logger?.error('Failed to update resource in Neptune', { error });\n throw error;\n }\n }\n \n async deleteResource(id: ResourceId): Promise<void> {\n try {\n // Delete the resource vertex and all connected edges\n await this.g.V()\n .hasLabel('Resource')\n .has('id', id)\n .drop()\n .iterate();\n\n this.logger?.info('Deleted resource from Neptune', { id });\n } catch (error) {\n this.logger?.error('Failed to delete resource from Neptune', { error });\n throw error;\n }\n }\n \n /**\n * Filtering, ranking and pagination happen in JS rather than in Gremlin.\n *\n * The ranking ladder (exact name over prefix over substring over path- or\n * tag-assisted) has no natural Gremlin expression, and a rank applied after\n * `range()` would order one page instead of the match set. JanusGraph\n * post-filters for the same reason. Both share `queryResources` with the\n * memory backend so search cannot mean three different things across three\n * gateways.\n *\n * The cost is explicit and accepted: this materializes every `Resource`\n * vertex per call, so it is O(N) in the size of the KB rather than in the\n * size of the result. Neo4j is the production path and pushes the whole\n * query — filter, rank, page — into Cypher; Neptune and JanusGraph are not\n * deployment targets today. If either becomes one at scale, the fix is a\n * Gremlin rank expression (`choose` over `toLower`, engine-version\n * permitting), not a return to per-gateway search semantics.\n */\n async listResources(filter: ResourceFilter): Promise<{ resources: ResourceDescriptor[]; total: number }> {\n try {\n const results = await this.g.V().hasLabel('Resource').elementMap().toList();\n return queryResources(results.map(vertexToResource), filter);\n } catch (error) {\n this.logger?.error('Failed to list resources from Neptune', { error });\n throw error;\n }\n }\n\n \n async createAnnotation(input: CreateAnnotationInternal): Promise<Annotation> {\n // The caller's id is the system of record's — never mint a fresh one\n // (the event-log id is what deletes and lookups arrive under).\n const annotation = buildAnnotation(input);\n const props = encodeAnnotation(annotation);\n const targetSource = props.resourceId!;\n const bodySource = props.source;\n const entityTypes = getEntityTypes(input);\n\n try {\n // Create Annotation vertex — every property comes from the codec, so\n // a source-only target contributes no `selector` property at all.\n let vertex = this.g.addV('Annotation');\n for (const [key, value] of Object.entries(props)) {\n vertex = vertex.property(key, value);\n }\n\n const newVertex = await vertex.next();\n\n // Create edge from Annotation to Resource (BELONGS_TO)\n await this.g.V(newVertex.value)\n .addE('BELONGS_TO')\n .to(this.g.V().hasLabel('Resource').has('id', targetSource)) // Use full URI\n .next();\n\n // If it's a resolved reference, create edge to target resource (REFERENCES)\n if (bodySource) {\n await this.g.V(newVertex.value)\n .addE('REFERENCES')\n .to(this.g.V().hasLabel('Resource').has('id', bodySource)) // Use full URI\n .next();\n }\n\n // Create TAGGED_AS relationships for entity types\n for (const entityType of entityTypes) {\n // Get or create EntityType vertex\n const etVertex = await this.g.V()\n .hasLabel('EntityType')\n .has('name', entityType)\n .fold()\n .coalesce(\n __.unfold(),\n this.g.addV('EntityType').property('name', entityType)\n )\n .next();\n\n // Create TAGGED_AS edge from Annotation to EntityType\n await this.g.V(newVertex.value)\n .addE('TAGGED_AS')\n .to(this.g.V(etVertex.value))\n .next();\n }\n\n this.logger?.info('Created annotation vertex in Neptune', { id: annotation.id });\n return annotation;\n } catch (error) {\n this.logger?.error('Failed to create annotation in Neptune', { error });\n throw error;\n }\n }\n \n async getAnnotation(id: AnnotationId): Promise<Annotation | null> {\n try {\n const result = await this.g.V()\n .hasLabel('Annotation')\n .has('id', id)\n .elementMap()\n .next();\n\n if (!result.value) {\n return null;\n }\n\n // Fetch entity types from TAGGED_AS relationships\n const entityTypesResult = await this.g.V()\n .hasLabel('Annotation')\n .has('id', id)\n .out('TAGGED_AS')\n .hasLabel('EntityType')\n .values('name')\n .toList();\n\n const entityTypes = entityTypesResult || [];\n\n return vertexToAnnotation(result.value, entityTypes);\n } catch (error) {\n this.logger?.error('Failed to get annotation from Neptune', { error });\n throw error;\n }\n }\n \n async updateAnnotation(id: AnnotationId, updates: Partial<Annotation>): Promise<Annotation> {\n try {\n let traversal = this.g.V()\n .hasLabel('Annotation')\n .has('id', id);\n\n // Update target properties\n if (updates.target !== undefined && typeof updates.target !== 'string') {\n if (updates.target.selector !== undefined) {\n for (const [key, value] of Object.entries(encodeSelector(updates.target.selector))) {\n traversal = traversal.property(key, value);\n }\n }\n }\n\n // Update body properties and entity types\n if (updates.body !== undefined) {\n const bodySource = getBodySource(updates.body);\n const entityTypes = getEntityTypes({ body: updates.body });\n\n if (bodySource) {\n traversal = traversal.property('source', bodySource);\n }\n\n // Update entity type relationships - remove old ones and create new ones\n if (entityTypes.length >= 0) {\n // Remove existing TAGGED_AS edges\n await this.g.V()\n .hasLabel('Annotation')\n .has('id', id)\n .outE('TAGGED_AS')\n .drop()\n .iterate();\n\n // Create new TAGGED_AS edges\n for (const entityType of entityTypes) {\n const etVertex = await this.g.V()\n .hasLabel('EntityType')\n .has('name', entityType)\n .fold()\n .coalesce(\n __.unfold(),\n this.g.addV('EntityType').property('name', entityType)\n )\n .next();\n\n await this.g.V()\n .hasLabel('Annotation')\n .has('id', id)\n .addE('TAGGED_AS')\n .to(this.g.V(etVertex.value))\n .next();\n }\n }\n }\n\n if (updates.modified !== undefined) {\n traversal = traversal.property('modified', updates.modified);\n }\n if (updates.generator !== undefined) {\n traversal = traversal.property('generator', JSON.stringify(updates.generator));\n }\n\n const result = await traversal.elementMap().next();\n\n if (!result.value) {\n throw new Error('Annotation not found');\n }\n\n // Fetch entity types from TAGGED_AS relationships\n const entityTypesResult = await this.g.V()\n .hasLabel('Annotation')\n .has('id', id)\n .out('TAGGED_AS')\n .hasLabel('EntityType')\n .values('name')\n .toList();\n\n const entityTypes = entityTypesResult || [];\n\n return vertexToAnnotation(result.value, entityTypes);\n } catch (error) {\n this.logger?.error('Failed to update annotation in Neptune', { error });\n throw error;\n }\n }\n \n async deleteAnnotation(id: AnnotationId): Promise<void> {\n try {\n await this.g.V()\n .hasLabel('Annotation')\n .has('id', id)\n .drop()\n .iterate();\n\n this.logger?.info('Deleted annotation from Neptune', { id });\n } catch (error) {\n this.logger?.error('Failed to delete annotation from Neptune', { error });\n throw error;\n }\n }\n \n async listAnnotations(filter: { resourceId?: ResourceId; type?: AnnotationCategory }): Promise<{ annotations: Annotation[]; total: number }> {\n try {\n let traversal = this.g.V().hasLabel('Annotation');\n\n // Apply filters\n if (filter.resourceId) {\n traversal = traversal.has('resourceId', filter.resourceId);\n }\n\n if (filter.type) {\n traversal = traversal.has('type', storedAnnotationType(motivationForCategory(filter.type)));\n }\n\n const results = await traversal.elementMap().toList();\n const annotations = await this.fetchAnnotationsWithEntityTypes(results);\n\n return { annotations, total: annotations.length };\n } catch (error) {\n this.logger?.error('Failed to list annotations from Neptune', { error });\n throw error;\n }\n }\n \n \n async getHighlights(resourceId: ResourceId): Promise<Annotation[]> {\n try {\n const results = await this.g.V()\n .hasLabel('Annotation')\n .has('resourceId', resourceId)\n .hasNot('resolvedResourceId')\n .elementMap()\n .toList();\n\n return await this.fetchAnnotationsWithEntityTypes(results);\n } catch (error) {\n this.logger?.error('Failed to get highlights from Neptune', { error });\n throw error;\n }\n }\n \n async resolveReference(annotationId: AnnotationId, source: ResourceId): Promise<Annotation> {\n try {\n // Get target resource name\n const targetDocResult = await this.g.V()\n .hasLabel('Resource')\n .has('id', source)\n .elementMap()\n .next();\n const targetDoc = targetDocResult.value ? vertexToResource(targetDocResult.value) : null;\n\n // Update the existing Annotation vertex\n const traversal = this.g.V()\n .hasLabel('Annotation')\n .has('id', annotationId)\n .property('source', source)\n .property('resolvedResourceName', targetDoc?.name)\n .property('resolvedAt', new Date().toISOString());\n\n const result = await traversal.elementMap().next();\n\n if (!result.value) {\n throw new Error('Annotation not found');\n }\n\n // Create REFERENCES edge to the resolved resource\n const annVertex = await this.g.V()\n .hasLabel('Annotation')\n .has('id', annotationId)\n .next();\n\n await this.g.V(annVertex.value)\n .addE('REFERENCES')\n .to(this.g.V().hasLabel('Resource').has('id', source))\n .next();\n\n // Fetch entity types from TAGGED_AS relationships\n const entityTypesResult = await this.g.V()\n .hasLabel('Annotation')\n .has('id', annotationId)\n .out('TAGGED_AS')\n .hasLabel('EntityType')\n .values('name')\n .toList();\n\n const entityTypes = entityTypesResult || [];\n\n return vertexToAnnotation(result.value, entityTypes);\n } catch (error) {\n this.logger?.error('Failed to resolve reference in Neptune', { error });\n throw error;\n }\n }\n \n async getReferences(resourceId: ResourceId): Promise<Annotation[]> {\n try {\n const results = await this.g.V()\n .hasLabel('Annotation')\n .has('resourceId', resourceId)\n .has('resolvedResourceId')\n .elementMap()\n .toList();\n\n return await this.fetchAnnotationsWithEntityTypes(results);\n } catch (error) {\n this.logger?.error('Failed to get references from Neptune', { error });\n throw error;\n }\n }\n \n async getEntityReferences(resourceId: ResourceId, entityTypes?: string[]): Promise<Annotation[]> {\n try {\n let traversal = this.g.V()\n .hasLabel('Annotation')\n .has('resourceId', resourceId)\n .has('resolvedResourceId')\n .has('entityTypes');\n \n if (entityTypes && entityTypes.length > 0) {\n traversal = traversal.filter(\n process.statics.or(\n ...entityTypes.map((type: string) =>\n process.statics.has('entityTypes', TextP.containing(`\"${type}\"`))\n )\n )\n );\n }\n \n const results = await traversal.elementMap().toList();\n\n return await this.fetchAnnotationsWithEntityTypes(results);\n } catch (error) {\n this.logger?.error('Failed to get entity references from Neptune', { error });\n throw error;\n }\n }\n \n async getResourceAnnotations(resourceId: ResourceId): Promise<Annotation[]> {\n try {\n const results = await this.g.V()\n .hasLabel('Annotation')\n .has('resourceId', resourceId)\n .elementMap()\n .toList();\n\n return await this.fetchAnnotationsWithEntityTypes(results);\n } catch (error) {\n this.logger?.error('Failed to get resource annotations from Neptune', { error });\n throw error;\n }\n }\n \n async getResourceReferencedBy(resourceId: ResourceId, _motivation?: string): Promise<Annotation[]> {\n try {\n const results = await this.g.V()\n .hasLabel('Annotation')\n .has('resolvedResourceId', resourceId)\n .elementMap()\n .toList();\n\n return await this.fetchAnnotationsWithEntityTypes(results);\n } catch (error) {\n this.logger?.error('Failed to get resource referenced by from Neptune', { error });\n throw error;\n }\n }\n \n async getResourceConnections(resourceId: ResourceId): Promise<GraphConnection[]> {\n try {\n // Get all annotations from this resource that reference other resources\n const outgoingAnnotations = await this.g.V()\n .hasLabel('Annotation')\n .has('resourceId', resourceId)\n .has('source')\n .elementMap()\n .toList();\n\n // Get all annotations that reference this resource\n const incomingAnnotations = await this.g.V()\n .hasLabel('Annotation')\n .has('source', resourceId)\n .elementMap()\n .toList();\n\n // Build connections map\n const connectionsMap = new Map<string, GraphConnection>();\n\n // Process outgoing references\n for (const annVertex of outgoingAnnotations) {\n const id = annVertex.properties?.id?.[0]?.value || annVertex.id;\n\n // Fetch entity types for this annotation\n const entityTypesResult = await this.g.V()\n .hasLabel('Annotation')\n .has('id', id)\n .out('TAGGED_AS')\n .hasLabel('EntityType')\n .values('name')\n .toList();\n\n const entityTypes = entityTypesResult || [];\n const annotation = vertexToAnnotation(annVertex, entityTypes);\n const targetDocId = getBodySource(annotation.body);\n if (!targetDocId) continue; // Skip stubs\n\n // Get the target resource\n const targetDocResult = await this.g.V()\n .hasLabel('Resource')\n .has('id', targetDocId)\n .elementMap()\n .next();\n\n if (targetDocResult.value) {\n const targetDoc = vertexToResource(targetDocResult.value);\n const targetDocId = getResourceId(targetDoc);\n if (!targetDocId) continue;\n const existing = connectionsMap.get(targetDocId);\n if (existing) {\n existing.annotations.push(annotation);\n } else {\n connectionsMap.set(targetDocId, {\n targetResource: targetDoc,\n annotations: [annotation],\n bidirectional: false,\n });\n }\n }\n }\n\n // Check for bidirectional connections\n for (const annVertex of incomingAnnotations) {\n const id = annVertex.properties?.id?.[0]?.value || annVertex.id;\n\n // Fetch entity types for this annotation\n const entityTypesResult = await this.g.V()\n .hasLabel('Annotation')\n .has('id', id)\n .out('TAGGED_AS')\n .hasLabel('EntityType')\n .values('name')\n .toList();\n\n const entityTypes = entityTypesResult || [];\n const annotation = vertexToAnnotation(annVertex, entityTypes);\n const sourceDocId = getTargetSource(annotation.target);\n const existing = connectionsMap.get(sourceDocId);\n if (existing) {\n existing.bidirectional = true;\n }\n }\n\n return Array.from(connectionsMap.values());\n } catch (error) {\n this.logger?.error('Failed to get resource connections from Neptune', { error });\n throw error;\n }\n }\n \n async findPath(fromResourceId: string, toResourceId: string, maxDepth: number = 5): Promise<GraphPath[]> {\n try {\n // Use Neptune's optimized path queries\n const results = await this.g.V()\n .hasLabel('Resource')\n .has('id', fromResourceId)\n .repeat(\n process.statics.both('REFERENCES')\n .simplePath()\n )\n .times(maxDepth)\n .emit()\n .has('id', toResourceId)\n .path()\n .by(process.statics.elementMap())\n .limit(10)\n .toList();\n \n const paths: GraphPath[] = [];\n \n for (const pathResult of results) {\n const resources: ResourceDescriptor[] = [];\n\n // Process path elements (alternating vertices and edges)\n for (let i = 0; i < pathResult.objects.length; i++) {\n const element = pathResult.objects[i];\n\n if (i % 2 === 0) {\n // Vertex (Resource)\n resources.push(vertexToResource(element));\n } else {\n // Edge - skip for now as we're using vertex-based annotations\n // We'd need to query for annotations between resources\n }\n }\n\n paths.push({ resources, annotations: [] });\n }\n \n return paths;\n } catch (error) {\n this.logger?.error('Failed to find paths in Neptune', { error });\n throw error;\n }\n }\n \n async getEntityTypeStats(): Promise<EntityTypeStats[]> {\n try {\n // Use Neptune's analytics capabilities\n const results = await this.g.V()\n .hasLabel('Resource')\n .values('entityTypes')\n .map((entityTypesJson: string) => {\n const types = JSON.parse(entityTypesJson);\n return types;\n })\n .unfold()\n .groupCount()\n .next();\n \n const stats: EntityTypeStats[] = [];\n \n if (results.value) {\n for (const [type, count] of Object.entries(results.value)) {\n stats.push({\n type,\n count: count as number,\n });\n }\n }\n \n return stats;\n } catch (error) {\n this.logger?.error('Failed to get entity type stats from Neptune', { error });\n throw error;\n }\n }\n \n async getStats(): Promise<{\n resourceCount: number;\n annotationCount: number;\n highlightCount: number;\n referenceCount: number;\n entityReferenceCount: number;\n entityTypes: Record<string, number>;\n contentTypes: Record<string, number>;\n }> {\n try {\n // Get resource count\n const docCountResult = await this.g.V()\n .hasLabel('Resource')\n .count()\n .next();\n const resourceCount = docCountResult.value || 0;\n \n // Get annotation count\n const selCountResult = await this.g.V()\n .hasLabel('Annotation')\n .count()\n .next();\n const annotationCount = selCountResult.value || 0;\n\n // Get highlight count (annotations without resolved resource)\n const highlightCountResult = await this.g.V()\n .hasLabel('Annotation')\n .hasNot('resolvedResourceId')\n .count()\n .next();\n const highlightCount = highlightCountResult.value || 0;\n\n // Get reference count (annotations with resolved resource)\n const referenceCountResult = await this.g.V()\n .hasLabel('Annotation')\n .has('resolvedResourceId')\n .count()\n .next();\n const referenceCount = referenceCountResult.value || 0;\n\n // Get entity reference count\n const entityRefCountResult = await this.g.V()\n .hasLabel('Annotation')\n .has('resolvedResourceId')\n .has('entityTypes')\n .count()\n .next();\n const entityReferenceCount = entityRefCountResult.value || 0;\n \n // Get entity type stats\n const entityTypeStats = await this.getEntityTypeStats();\n const entityTypes: Record<string, number> = {};\n for (const stat of entityTypeStats) {\n entityTypes[stat.type] = stat.count;\n }\n \n // Get content type stats\n const contentTypeResult = await this.g.V()\n .hasLabel('Resource')\n .groupCount()\n .by('contentType')\n .next();\n const contentTypes = contentTypeResult.value || {};\n \n return {\n resourceCount,\n annotationCount,\n highlightCount,\n referenceCount,\n entityReferenceCount,\n entityTypes,\n contentTypes,\n };\n } catch (error) {\n this.logger?.error('Failed to get stats from Neptune', { error });\n throw error;\n }\n }\n \n async batchCreateResources(resources: ResourceDescriptor[]): Promise<ResourceDescriptor[]> {\n const results: ResourceDescriptor[] = [];\n for (const resource of resources) {\n results.push(await this.createResource(resource));\n }\n return results;\n }\n\n async createAnnotations(inputs: CreateAnnotationInternal[]): Promise<Annotation[]> {\n const results: Annotation[] = [];\n\n try {\n for (const input of inputs) {\n const annotation = await this.createAnnotation(input);\n results.push(annotation);\n }\n\n return results;\n } catch (error) {\n this.logger?.error('Failed to create annotations in Neptune', { error });\n throw error;\n }\n }\n\n\n async resolveReferences(inputs: { annotationId: AnnotationId; source: ResourceId }[]): Promise<Annotation[]> {\n const results: Annotation[] = [];\n\n try {\n for (const input of inputs) {\n const annotation = await this.resolveReference(input.annotationId, input.source);\n results.push(annotation);\n }\n\n return results;\n } catch (error) {\n this.logger?.error('Failed to resolve references in Neptune', { error });\n throw error;\n }\n }\n \n async detectAnnotations(_resourceId: ResourceId): Promise<Annotation[]> {\n // This would use AI/ML to detect annotations in a resource\n // For now, return empty array as a placeholder\n return [];\n }\n \n // Tag Collections - stored as special vertices in the graph\n private entityTypesCollection: Set<string> | null = null;\n \n async getEntityTypes(): Promise<string[]> {\n // Initialize if not already loaded\n if (this.entityTypesCollection === null) {\n await this.initializeTagCollections();\n }\n return Array.from(this.entityTypesCollection!).sort();\n }\n \n async addEntityType(tag: string): Promise<void> {\n if (this.entityTypesCollection === null) {\n await this.initializeTagCollections();\n }\n this.entityTypesCollection!.add(tag);\n // Persist to Neptune\n try {\n await this.g.V()\n .has('tagCollection', 'type', 'entity-types')\n .fold()\n .coalesce(\n __.unfold(),\n __.addV('TagCollection').property('type', 'entity-types')\n )\n .property(cardinality.set, 'tags', tag)\n .iterate();\n } catch (error) {\n this.logger?.error('Failed to add entity type', { error });\n }\n }\n \n async addEntityTypes(tags: string[]): Promise<void> {\n if (this.entityTypesCollection === null) {\n await this.initializeTagCollections();\n }\n tags.forEach(tag => this.entityTypesCollection!.add(tag));\n // Persist to Neptune\n try {\n const vertex = await this.g.V()\n .has('tagCollection', 'type', 'entity-types')\n .fold()\n .coalesce(\n __.unfold(),\n __.addV('TagCollection').property('type', 'entity-types')\n );\n \n for (const tag of tags) {\n await vertex.property(cardinality.set, 'tags', tag).iterate();\n }\n } catch (error) {\n this.logger?.error('Failed to add entity types', { error });\n }\n }\n \n private async initializeTagCollections(): Promise<void> {\n try {\n // Check Neptune for existing collections\n const collections = await this.g.V()\n .hasLabel('TagCollection')\n .project('type', 'tags')\n .by('type')\n .by(__.values('tags').fold())\n .toList();\n\n // Process existing collections\n for (const col of collections) {\n if (col.type === 'entity-types') {\n this.entityTypesCollection = new Set(col.tags as string[]);\n }\n }\n } catch (error) {\n this.logger?.debug('No existing tag collections found, will initialize with defaults');\n }\n\n // Initialize with defaults if not present\n if (this.entityTypesCollection === null) {\n const { DEFAULT_ENTITY_TYPES } = await import('@semiont/ontology');\n this.entityTypesCollection = new Set(DEFAULT_ENTITY_TYPES);\n // Persist defaults to Neptune\n try {\n const vertex = await this.g.addV('TagCollection')\n .property('type', 'entity-types')\n .next();\n for (const tag of DEFAULT_ENTITY_TYPES) {\n await this.g.V(vertex.value.id)\n .property(cardinality.set, 'tags', tag)\n .iterate();\n }\n } catch (error) {\n this.logger?.error('Failed to initialize entity types', { error });\n }\n }\n }\n \n generateId(): string {\n return uuidv4().replace(/-/g, '').substring(0, 12);\n }\n \n async clearDatabase(): Promise<void> {\n try {\n // CAREFUL! This clears the entire graph\n await this.g.V().drop().iterate();\n this.logger?.info('Cleared all data from Neptune');\n // Reset tag collections\n this.entityTypesCollection = null;\n } catch (error) {\n this.logger?.error('Failed to clear Neptune database', { error });\n throw error;\n }\n }\n}","/**\n * The annotation codec — the one module that decides how a W3C annotation\n * becomes stored properties and back.\n *\n * Every store keeps its own dialect (Cypher parameters, Gremlin\n * `.property()` chains, a Map) and its own way of flattening what the driver\n * hands back into a property bag. What none of them owns any more is the\n * SHAPE: the W3C envelope, which fields are required, how a selector is\n * serialized, how the body array is reconstructed from entity tags and a\n * linking source. Those lived in three near-verbatim copies that disagreed\n * in four places, and each disagreement was a bug — a resource-level\n * annotation came back carrying `selector: {}`, which is not a legal\n * selector, and a motivation-less row was silently relabelled `'linking'`.\n *\n * The codec manufactures nothing. Absence is stored as absence and read back\n * as absence, in both directions.\n */\n\nimport { annotationId as makeAnnotationId } from '@semiont/core';\nimport { getBodySource, getExactText, getTargetSelector, getTargetSource } from '@semiont/core';\nimport { getEntityTypes } from '@semiont/ontology';\nimport type { Annotation, AnnotationCategory, CreateAnnotationInternal } from '@semiont/core';\n\n/**\n * A store's property bag, flattened. Producing this is the store's job (D3):\n * neo4j unwraps `node.properties` and its native temporals, the Gremlin\n * stores unwrap `[{value}]` lists. What the values MEAN is the codec's.\n */\nexport type AnnotationProperties = Record<string, string | undefined>;\n\ntype AnnotationTarget = Exclude<Annotation['target'], string>;\ntype AnnotationSelector = NonNullable<AnnotationTarget['selector']>;\ntype AnnotationBody = NonNullable<Annotation['body']>;\n\n/**\n * The stored `type` property, which the category filters match on. It\n * restates the motivation, so it is derived from it here and nowhere else —\n * the three filters that used to hand-write the same mapping had drifted\n * into asking for a value no store ever wrote.\n */\nexport function storedAnnotationType(motivation: Annotation['motivation']): string {\n return motivation === 'highlighting' ? 'TextualBody' : 'SpecificResource';\n}\n\n/** The category a caller filters by, in the vocabulary the annotation stores. */\nexport function motivationForCategory(category: AnnotationCategory): Annotation['motivation'] {\n return category === 'highlight' ? 'highlighting' : 'linking';\n}\n\n/**\n * Mint the annotation a create request describes.\n *\n * `created` comes from the input, which carries the AUTHORED moment from the\n * event. It used to be a second parameter, and every store passed\n * `new Date().toISOString()` into it — so the graph stamped its own write time\n * and a rebuild collapsed every annotation to the rebuild moment.\n */\nexport function buildAnnotation(input: CreateAnnotationInternal): Annotation {\n const annotation: Annotation = {\n '@context': 'http://www.w3.org/ns/anno.jsonld',\n type: 'Annotation',\n id: makeAnnotationId(input.id),\n motivation: input.motivation,\n target: input.target,\n creator: input.creator,\n created: input.created,\n };\n if (input.body && (!Array.isArray(input.body) || input.body.length > 0)) {\n annotation.body = input.body;\n }\n return annotation;\n}\n\n/**\n * The annotation's stored properties. Entity tags are not among them — those\n * are edges, and the store writes them from `getEntityTypes(annotation)`.\n */\nexport function encodeAnnotation(annotation: Annotation): Record<string, string> {\n const selector = getTargetSelector(annotation.target);\n const bodySource = getBodySource(annotation.body);\n\n const resourceId = getTargetSource(annotation.target);\n if (!resourceId) throw new Error(`Annotation ${annotation.id} has no target source`);\n\n const props: Record<string, string> = {\n id: annotation.id,\n resourceId,\n type: storedAnnotationType(annotation.motivation),\n motivation: annotation.motivation,\n creator: JSON.stringify(annotation.creator),\n created: annotation.created,\n };\n\n if (selector) Object.assign(props, encodeSelector(selector));\n if (bodySource) props.source = bodySource;\n if (annotation.modified) props.modified = annotation.modified;\n if (annotation.generator) props.generator = JSON.stringify(annotation.generator);\n\n return props;\n}\n\n/**\n * The properties a selector contributes: its serialization, plus the quoted\n * text pulled out beside it. Targeted selector updates go through here too,\n * so no store decides on its own what a selector is called on disk.\n */\nexport function encodeSelector(selector: AnnotationSelector): Record<string, string> {\n const props: Record<string, string> = { selector: JSON.stringify(selector) };\n const exact = getExactText(selector);\n if (exact) props.exact = exact;\n return props;\n}\n\n/**\n * Rebuild the annotation from stored properties and the entity-tag edges the\n * store resolved separately.\n *\n * A field the properties do not carry is omitted, never invented: a\n * source-only target (legal since RESOURCE-LEVEL-ANCHOR) comes back with no\n * `selector`, and a row missing a required field fails loudly by name rather\n * than acquiring a default.\n */\nexport function decodeAnnotation(props: AnnotationProperties, entityTypes: string[] = []): Annotation {\n const id = props.id;\n if (!id) throw new Error('Annotation missing required field: id');\n\n const required = (key: string): string => {\n const value = props[key];\n if (!value) throw new Error(`Annotation ${id} missing required field: ${key}`);\n return value;\n };\n\n const resourceId = required('resourceId');\n const creator = JSON.parse(required('creator'));\n // The stored value is one of the wire vocabulary's, which the event that\n // produced it was validated against; the projection does not re-police it.\n const motivation = required('motivation') as Annotation['motivation'];\n const created = required('created');\n\n const body: AnnotationBody = [];\n for (const entityType of entityTypes) {\n if (entityType) body.push({ type: 'TextualBody', value: entityType, purpose: 'tagging' });\n }\n if (props.source) {\n body.push({ type: 'SpecificResource', source: props.source, purpose: 'linking' });\n }\n\n const selector = decodeSelector(props.selector);\n const target: AnnotationTarget = selector ? { source: resourceId, selector } : { source: resourceId };\n\n const annotation: Annotation = {\n '@context': 'http://www.w3.org/ns/anno.jsonld',\n type: 'Annotation',\n id: makeAnnotationId(id),\n motivation,\n target,\n creator,\n created,\n };\n\n if (body.length > 0) annotation.body = body;\n if (props.modified) annotation.modified = props.modified;\n if (props.generator) {\n try {\n annotation.generator = JSON.parse(props.generator);\n } catch {\n // A corrupt generator is not worth failing the whole read over — the\n // annotation itself is intact, and provenance is advisory.\n }\n }\n\n return annotation;\n}\n\n/**\n * Rows written before RESOURCE-LEVEL-ANCHOR reached the stores hold `'{}'`\n * where a resource-level annotation has no selector at all. `{}` satisfies no\n * branch of the selector union, so it fails validation on the first round\n * trip through a validated channel — reading it back as absent is what makes\n * those rows harmless without a migration.\n */\nfunction decodeSelector(raw: string | undefined): AnnotationSelector | undefined {\n if (!raw) return undefined;\n const parsed = JSON.parse(raw);\n if (!parsed || Object.keys(parsed).length === 0) return undefined;\n return parsed;\n}\n\n/**\n * What the graph is SUPPOSED to hold for this annotation — the codec's own\n * statement of it, obtained by round-tripping through both halves.\n *\n * The graph is a purpose-built projection, not a copy of the views: it stores\n * what graph queries need and nothing else. `wasAttributedTo`, for instance,\n * rides on almost every annotation in the log and the encoder deliberately\n * writes none of it. So \"is the graph correct?\" cannot be answered by comparing\n * it to a view — only by comparing it to what this module says it should be.\n *\n * Callers get a value scoped to exactly the fields the encoder writes, in the\n * decoded shape, free of any store's physical dialect. Widen or narrow the\n * encoder and this follows automatically; there is no second list to maintain.\n */\nexport function intendedGraphAnnotation(annotation: Annotation): Annotation {\n return decodeAnnotation(encodeAnnotation(annotation), getEntityTypes(annotation));\n}\n","// Neo4j implementation of GraphDatabase interface\n// Uses Cypher query language\n\nimport type { Driver, Session } from 'neo4j-driver';\nimport { GraphDatabase } from '../interface';\nimport { assertMutableResourceUpdate } from '../interface';\nimport { searchTerms } from '../resource-query';\nimport type { Logger } from '@semiont/core';\nimport type {\n AnnotationCategory,\n GraphConnection,\n GraphPath,\n EntityTypeStats,\n ResourceFilter,\n UpdateResourceInput,\n CreateAnnotationInternal,\n ResourceId,\n AnnotationId,\n} from '@semiont/core';\nimport { v4 as uuidv4 } from 'uuid';\nimport { getPrimaryRepresentation, getStorageUri } from '@semiont/core';\nimport { getEntityTypes } from '@semiont/ontology';\nimport {\n buildAnnotation,\n decodeAnnotation,\n encodeAnnotation,\n motivationForCategory,\n storedAnnotationType,\n type AnnotationProperties,\n} from '../annotation-codec';\n\nimport type { ResourceDescriptor } from '@semiont/core';\nimport type { Annotation } from '@semiont/core';\n\n/**\n * Convert motivation to a valid Neo4j label name\n *\n * Annotations get both a property (`motivation: \"linking\"`) and a label (`:Linking`)\n * for the same motivation value. This enables:\n * - Fast filtering: `MATCH (a:Annotation:Linking)` vs `MATCH (a:Annotation) WHERE a.motivation = 'linking'`\n * - Automatic indexing: Neo4j indexes labels by default\n * - Visual exploration: Graph visualization tools prominently display labels\n *\n * Example: \"linking\" -> \"Linking\", \"commenting\" -> \"Commenting\"\n *\n * W3C Motivation values:\n * assessing, bookmarking, classifying, commenting, describing, editing,\n * highlighting, identifying, linking, moderating, questioning, replying, tagging\n */\nfunction motivationToLabel(motivation: string): string {\n return motivation.charAt(0).toUpperCase() + motivation.slice(1);\n}\n\nexport class Neo4jGraphDatabase implements GraphDatabase {\n private driver: Driver | null = null;\n private neo4j!: typeof import('neo4j-driver');\n private connected: boolean = false;\n private logger?: Logger;\n private config: {\n uri?: string;\n username?: string;\n password?: string;\n database?: string;\n };\n\n // Tag Collections - cached in memory for performance\n private entityTypesCollection: Set<string> | null = null;\n\n constructor(config: {\n uri?: string;\n username?: string;\n password?: string;\n database?: string;\n logger?: Logger;\n } = {}) {\n this.config = config;\n this.logger = config.logger;\n }\n\n async connect(): Promise<void> {\n try {\n const uri = this.config.uri;\n const username = this.config.username;\n const password = this.config.password;\n const database = this.config.database;\n\n if (!uri) {\n throw new Error('Neo4j URI not configured! Pass uri in config.');\n }\n if (!username) {\n throw new Error('Neo4j username not configured! Pass username in config.');\n }\n if (!password) {\n throw new Error('Neo4j password not configured! Pass password in config.');\n }\n if (!database) {\n throw new Error('Neo4j database not configured! Pass database in config.');\n }\n\n this.logger?.info('Connecting to Neo4j', { uri });\n\n this.neo4j = await import('neo4j-driver');\n this.driver = this.neo4j.driver(\n uri,\n this.neo4j.auth.basic(username, password),\n {\n maxConnectionPoolSize: 50,\n connectionAcquisitionTimeout: 60000,\n }\n );\n\n // Test connection\n const session = this.driver.session({ database });\n\n await session.run('RETURN 1 as test');\n await session.close();\n\n // Create constraints and indexes if they don't exist\n await this.ensureSchemaExists();\n\n this.logger?.info('Successfully connected to Neo4j');\n this.connected = true;\n } catch (error) {\n this.logger?.error('Failed to connect to Neo4j', { error });\n throw new Error(`Neo4j connection failed: ${error}`);\n }\n }\n\n async disconnect(): Promise<void> {\n if (this.driver) {\n await this.driver.close();\n this.driver = null;\n }\n this.connected = false;\n }\n\n isConnected(): boolean {\n return this.connected;\n }\n\n private getSession(): Session {\n if (!this.driver) {\n throw new Error('Neo4j driver not initialized');\n }\n if (!this.config.database) {\n throw new Error('Neo4j database not configured! Pass database in config.');\n }\n return this.driver.session({\n database: this.config.database\n });\n }\n\n private async ensureSchemaExists(): Promise<void> {\n const session = this.getSession();\n try {\n // Create constraints for unique IDs\n const constraints = [\n 'CREATE CONSTRAINT doc_id IF NOT EXISTS FOR (d:Resource) REQUIRE d.id IS UNIQUE',\n 'CREATE CONSTRAINT sel_id IF NOT EXISTS FOR (s:Annotation) REQUIRE s.id IS UNIQUE',\n 'CREATE CONSTRAINT tag_id IF NOT EXISTS FOR (t:TagCollection) REQUIRE t.type IS UNIQUE'\n ];\n\n for (const constraint of constraints) {\n try {\n await session.run(constraint);\n } catch (error: any) {\n // Ignore if constraint already exists\n if (!error.message?.includes('already exists')) {\n this.logger?.warn('Schema creation warning', { message: error.message });\n }\n }\n }\n\n // Create indexes for common queries\n const indexes = [\n 'CREATE INDEX doc_name IF NOT EXISTS FOR (d:Resource) ON (d.name)',\n 'CREATE INDEX doc_entity_types IF NOT EXISTS FOR (d:Resource) ON (d.entityTypes)',\n 'CREATE INDEX sel_doc_id IF NOT EXISTS FOR (s:Annotation) ON (s.resourceId)',\n 'CREATE INDEX sel_resolved_id IF NOT EXISTS FOR (s:Annotation) ON (s.resolvedResourceId)'\n ];\n\n for (const index of indexes) {\n try {\n await session.run(index);\n } catch (error: any) {\n // Ignore if index already exists\n if (!error.message?.includes('already exists')) {\n this.logger?.warn('Index creation warning', { message: error.message });\n }\n }\n }\n } finally {\n await session.close();\n }\n }\n\n async createResource(resource: ResourceDescriptor): Promise<ResourceDescriptor> {\n const session = this.getSession();\n try {\n const id = resource['@id']; // Use full URI for consistency\n const primaryRep = getPrimaryRepresentation(resource);\n if (!primaryRep) {\n throw new Error('Resource must have at least one representation');\n }\n\n // Use MERGE instead of CREATE for idempotence and to enrich stub nodes\n // Stub nodes may be created by REFERENCES edge creation before resource.created event\n const result = await session.run(\n `MERGE (d:Resource {id: $id})\n SET d.name = $name,\n d.entityTypes = $entityTypes,\n d.format = $format,\n d.archived = $archived,\n d.created = $created,\n d.creator = $creator,\n d.contentChecksum = $contentChecksum,\n d.sourceAnnotationId = $sourceAnnotationId,\n d.sourceResourceId = $sourceResourceId,\n d.storageUri = $storageUri,\n d.stub = false\n RETURN d`,\n {\n id,\n name: resource.name,\n entityTypes: resource.entityTypes,\n format: primaryRep.mediaType,\n archived: resource.archived || false,\n created: resource.dateCreated,\n creator: JSON.stringify(resource.wasAttributedTo),\n contentChecksum: primaryRep.checksum,\n sourceAnnotationId: resource.sourceAnnotationId ?? null,\n sourceResourceId: resource.sourceResourceId ?? null,\n storageUri: getStorageUri(resource) ?? null,\n }\n );\n\n this.logger?.info('Resource created/enriched', { id });\n return this.parseResourceNode(result.records[0]!.get('d'));\n } finally {\n await session.close();\n }\n }\n\n async getResource(id: ResourceId): Promise<ResourceDescriptor | null> {\n const session = this.getSession();\n try {\n const result = await session.run(\n 'MATCH (d:Resource {id: $id}) RETURN d',\n { id }\n );\n\n if (result.records.length === 0) return null;\n return this.parseResourceNode(result.records[0]!.get('d'));\n } finally {\n await session.close();\n }\n }\n\n async updateResource(id: ResourceId, input: UpdateResourceInput): Promise<ResourceDescriptor> {\n assertMutableResourceUpdate(input);\n\n const sets: string[] = [];\n const params: Record<string, unknown> = { id };\n if (input.archived !== undefined) {\n sets.push('d.archived = $archived');\n params.archived = input.archived;\n }\n if (input.entityTypes !== undefined) {\n sets.push('d.entityTypes = $entityTypes');\n params.entityTypes = input.entityTypes;\n }\n\n const session = this.getSession();\n try {\n const result = await session.run(\n `MATCH (d:Resource {id: $id})\n SET ${sets.join(', ')}\n RETURN d`,\n params\n );\n\n if (result.records.length === 0) {\n throw new Error('Resource not found');\n }\n\n return this.parseResourceNode(result.records[0]!.get('d'));\n } finally {\n await session.close();\n }\n }\n\n async deleteResource(id: ResourceId): Promise<void> {\n const session = this.getSession();\n try {\n // Delete resource and all its annotations\n await session.run(\n `MATCH (d:Resource {id: $id})\n OPTIONAL MATCH (a:Annotation)-[:BELONGS_TO|:REFERENCES]->(d)\n DETACH DELETE d, a`,\n { id }\n );\n } finally {\n await session.close();\n }\n }\n\n async listResources(filter: ResourceFilter): Promise<{ resources: ResourceDescriptor[]; total: number }> {\n const session = this.getSession();\n try {\n let whereClause = '';\n const params: any = {};\n // Stub nodes are id-only placeholders that `MERGE` creates when a\n // REFERENCES edge points at a resource whose `resource.created` event\n // hasn't landed yet. They carry no name, so they are not listable — and\n // `parseResourceNode` throws on the missing field rather than inventing one.\n const conditions: string[] = ['coalesce(d.stub, false) = false'];\n\n if (filter.archived !== undefined) {\n conditions.push('d.archived = $archived');\n params.archived = filter.archived;\n }\n\n if (filter.entityTypes && filter.entityTypes.length > 0) {\n conditions.push('ANY(type IN $entityTypes WHERE type IN d.entityTypes)');\n params.entityTypes = filter.entityTypes;\n }\n\n // Every term must appear, each satisfiable by the name or the path. A\n // whitespace-only query yields no terms and so is not a search at all.\n const terms = filter.search ? searchTerms(filter.search) : [];\n if (terms.length > 0) {\n conditions.push(\n `ALL(t IN $terms WHERE toLower(d.name) CONTAINS t\n OR toLower(coalesce(d.storageUri, \"\")) CONTAINS t\n OR ANY(e IN coalesce(d.entityTypes, []) WHERE toLower(e) CONTAINS t))`\n );\n params.terms = terms;\n params.search = filter.search!.trim().toLowerCase();\n }\n\n if (conditions.length > 0) {\n whereClause = 'WHERE ' + conditions.join(' AND ');\n }\n\n // Get total count\n const countResult = await session.run(\n `MATCH (d:Resource) ${whereClause} RETURN count(d) as total`,\n params\n );\n const total = countResult.records[0]!.get('total').toNumber();\n\n // Get paginated results - ensure integers for Neo4j\n params.skip = this.neo4j.int(filter.offset || 0);\n params.limit = this.neo4j.int(filter.limit || 20);\n\n // Rank only means something against a query; an unsearched listing orders\n // on recency alone. Ranking must happen here rather than over the returned\n // page, or it would sort one page instead of the match set.\n const rankClause = terms.length > 0\n ? `WITH d, CASE\n WHEN toLower(d.name) = $search THEN 0\n WHEN toLower(d.name) STARTS WITH $search THEN 1\n WHEN ALL(t IN $terms WHERE toLower(d.name) CONTAINS t) THEN 2\n ELSE 3\n END AS rank\n `\n : '';\n const orderClause = terms.length > 0\n ? 'ORDER BY rank, d.created DESC, d.id'\n : 'ORDER BY d.created DESC, d.id';\n\n const result = await session.run(\n `MATCH (d:Resource) ${whereClause}\n ${rankClause}RETURN d\n ${orderClause}\n SKIP $skip LIMIT $limit`,\n params\n );\n\n const resources = result.records.map(record => this.parseResourceNode(record.get('d')));\n\n return { resources, total };\n } finally {\n await session.close();\n }\n }\n\n\n async createAnnotation(input: CreateAnnotationInternal): Promise<Annotation> {\n const session = this.getSession();\n try {\n const annotation = buildAnnotation(input);\n const props = encodeAnnotation(annotation);\n const targetSource = props.resourceId!;\n const bodySource = props.source;\n\n // Entity tags are edges, not properties, so they travel beside the bag.\n const entityTypes = getEntityTypes(input);\n\n // Convert motivation to label (e.g., \"linking\" -> \"Linking\")\n const motivationLabel = motivationToLabel(annotation.motivation);\n\n // The codec's property bag is applied verbatim; `created` is then\n // re-set as a native temporal, which is the one property this store\n // stores in a type of its own.\n const cypher = bodySource\n ? `MATCH (from:Resource {id: $targetSource})\n MATCH (to:Resource {id: $bodySource})\n CREATE (a:Annotation:${motivationLabel})\n SET a = $props\n CREATE (a)-[:BELONGS_TO]->(from)\n CREATE (a)-[:REFERENCES]->(to)\n FOREACH (entityType IN $entityTypes |\n MERGE (et:EntityType {name: entityType})\n CREATE (a)-[:TAGGED_AS]->(et)\n )\n RETURN a`\n : `MATCH (d:Resource {id: $targetSource})\n CREATE (a:Annotation:${motivationLabel})\n SET a = $props\n CREATE (a)-[:BELONGS_TO]->(d)\n FOREACH (entityType IN $entityTypes |\n MERGE (et:EntityType {name: entityType})\n CREATE (a)-[:TAGGED_AS]->(et)\n )\n RETURN a`;\n\n const result = await session.run(cypher, {\n props,\n targetSource,\n bodySource: bodySource ?? null,\n entityTypes,\n });\n\n if (result.records.length === 0) {\n throw new Error(`Failed to create annotation: Resource ${targetSource} not found in graph database`);\n }\n\n return parseAnnotationNode(result.records[0]!.get('a'), entityTypes);\n } finally {\n await session.close();\n }\n }\n\n async getAnnotation(id: AnnotationId): Promise<Annotation | null> {\n this.logger?.debug('Getting annotation', { id });\n const session = this.getSession();\n try {\n const result = await session.run(\n `MATCH (a:Annotation {id: $id})\n OPTIONAL MATCH (a)-[:TAGGED_AS]->(et:EntityType)\n RETURN a, collect(et.name) as entityTypes`,\n { id }\n );\n\n if (result.records.length === 0) {\n this.logger?.debug('Annotation not found', { id });\n return null;\n }\n this.logger?.debug('Annotation found', { id });\n return parseAnnotationNode(\n result.records[0]!.get('a'),\n result.records[0]!.get('entityTypes')\n );\n } finally {\n await session.close();\n }\n }\n\n async updateAnnotation(id: AnnotationId, updates: Partial<Annotation>): Promise<Annotation> {\n const session = this.getSession();\n try {\n const setClauses: string[] = ['a.updatedAt = datetime()'];\n const params: any = { id };\n\n // Build SET clauses dynamically\n Object.entries(updates).forEach(([key, value]) => {\n if (key !== 'id' && key !== 'updatedAt') {\n setClauses.push(`a.${key} = $${key}`);\n if (key === 'body') {\n params[key] = JSON.stringify(value);\n } else if (key === 'created') {\n params[key] = value ? new Date(value as any).toISOString() : null;\n } else {\n params[key] = value;\n }\n }\n });\n\n // Update annotation properties\n const result = await session.run(\n `MATCH (a:Annotation {id: $id})\n SET ${setClauses.join(', ')}\n WITH a\n OPTIONAL MATCH (a)-[:TAGGED_AS]->(et:EntityType)\n RETURN a, collect(et.name) as entityTypes`,\n params\n );\n\n if (result.records.length === 0) {\n throw new Error('Annotation not found');\n }\n\n // If motivation was updated, update the label\n if (updates.motivation) {\n const newLabel = motivationToLabel(updates.motivation);\n this.logger?.debug('Updating motivation label', { newLabel });\n\n // Remove all possible motivation labels and add the new one\n const allMotivations = ['Assessing', 'Bookmarking', 'Classifying', 'Commenting',\n 'Describing', 'Editing', 'Highlighting', 'Identifying',\n 'Linking', 'Moderating', 'Questioning', 'Replying', 'Tagging'];\n const removeLabels = allMotivations.filter(m => m !== newLabel).map(m => `a:${m}`).join(', ');\n\n await session.run(\n `MATCH (a:Annotation {id: $id})\n REMOVE ${removeLabels}\n SET a:${newLabel}`,\n { id }\n );\n this.logger?.debug('Motivation label updated', { newLabel });\n }\n\n // If body was updated and contains a SpecificResource, create REFERENCES relationship\n if (updates.body) {\n this.logger?.debug('Body update for annotation', { id, body: updates.body });\n const bodyArray = Array.isArray(updates.body) ? updates.body : [updates.body];\n\n const specificResource = bodyArray.find((item: any) => item.type === 'SpecificResource' && item.purpose === 'linking');\n\n if (specificResource && 'source' in specificResource && specificResource.source) {\n this.logger?.debug('Creating REFERENCES edge', { annotationId: id, targetResourceId: specificResource.source });\n // Create REFERENCES relationship to the target resource\n // Use MERGE for target to create stub node if it doesn't exist yet (eventual consistency)\n // Stub will be enriched when resource.created event arrives\n const refResult = await session.run(\n `MATCH (a:Annotation {id: $annotationId})\n MERGE (target:Resource {id: $targetResourceId})\n ON CREATE SET target.stub = true\n MERGE (a)-[:REFERENCES]->(target)\n RETURN a, target, target.stub AS wasStub`,\n {\n annotationId: id,\n targetResourceId: specificResource.source\n }\n );\n\n if (refResult.records.length > 0) {\n const wasStub = refResult.records[0]!.get('wasStub');\n if (wasStub) {\n this.logger?.debug('REFERENCES edge created with stub node', { targetResourceId: specificResource.source });\n } else {\n this.logger?.debug('REFERENCES edge created to existing resource', { targetResourceId: specificResource.source });\n }\n } else {\n this.logger?.warn('REFERENCES edge creation returned no records');\n }\n } else {\n this.logger?.debug('No SpecificResource in body - stub reference not yet resolved');\n }\n } else {\n this.logger?.debug('No body update for annotation', { id });\n }\n\n return parseAnnotationNode(\n result.records[0]!.get('a'),\n result.records[0]!.get('entityTypes')\n );\n } finally {\n await session.close();\n }\n }\n\n async deleteAnnotation(id: AnnotationId): Promise<void> {\n const session = this.getSession();\n try {\n await session.run(\n 'MATCH (a:Annotation {id: $id}) DETACH DELETE a',\n { id }\n );\n } finally {\n await session.close();\n }\n }\n\n async listAnnotations(filter: { resourceId?: ResourceId; type?: AnnotationCategory }): Promise<{ annotations: Annotation[]; total: number }> {\n const session = this.getSession();\n try {\n const conditions: string[] = [];\n const params: any = {};\n\n if (filter.resourceId) {\n conditions.push('a.resourceId = $resourceId');\n params.resourceId = filter.resourceId;\n }\n\n if (filter.type) {\n conditions.push('a.type = $type');\n params.type = storedAnnotationType(motivationForCategory(filter.type));\n }\n\n const whereClause = conditions.length > 0 ? 'WHERE ' + conditions.join(' AND ') : '';\n\n // Get all results (no pagination in new simplified interface)\n const result = await session.run(\n `MATCH (a:Annotation) ${whereClause}\n OPTIONAL MATCH (a)-[:TAGGED_AS]->(et:EntityType)\n RETURN a, collect(et.name) as entityTypes`,\n params\n );\n\n const annotations = result.records.map(record =>\n parseAnnotationNode(record.get('a'), record.get('entityTypes'))\n );\n\n return { annotations, total: annotations.length };\n } finally {\n await session.close();\n }\n }\n\n async getHighlights(resourceId: ResourceId): Promise<Annotation[]> {\n const session = this.getSession();\n try {\n const result = await session.run(\n `MATCH (a:Annotation {resourceId: $resourceId})\n WHERE a.annotationCategory = 'highlight'\n OPTIONAL MATCH (a)-[:TAGGED_AS]->(et:EntityType)\n RETURN a, collect(et.name) as entityTypes\n ORDER BY a.created DESC`,\n { resourceId }\n );\n\n return result.records.map(record =>\n parseAnnotationNode(record.get('a'), record.get('entityTypes'))\n );\n } finally {\n await session.close();\n }\n }\n\n async resolveReference(annotationId: AnnotationId, source: ResourceId): Promise<Annotation> {\n const session = this.getSession();\n try {\n // Get the target resource's name\n const docResult = await session.run(\n 'MATCH (d:Resource {id: $id}) RETURN d.name as name',\n { id: source }\n );\n const resourceName = docResult.records[0]?.get('name');\n\n // Update annotation and create REFERENCES relationship\n const result = await session.run(\n `MATCH (a:Annotation {id: $annotationId})\n MATCH (to:Resource {id: $source})\n SET a.source = $source,\n a.resolvedResourceName = $resourceName,\n a.resolvedAt = datetime()\n MERGE (a)-[:REFERENCES]->(to)\n OPTIONAL MATCH (a)-[:TAGGED_AS]->(et:EntityType)\n RETURN a, collect(et.name) as entityTypes`,\n { annotationId, source, resourceName }\n );\n\n if (result.records.length === 0) {\n throw new Error('Annotation not found');\n }\n\n return parseAnnotationNode(\n result.records[0]!.get('a'),\n result.records[0]!.get('entityTypes')\n );\n } finally {\n await session.close();\n }\n }\n\n async getReferences(resourceId: ResourceId): Promise<Annotation[]> {\n const session = this.getSession();\n try {\n const result = await session.run(\n `MATCH (a:Annotation {resourceId: $resourceId})\n WHERE a.annotationCategory IN ['stub_reference', 'resolved_reference']\n OPTIONAL MATCH (a)-[:TAGGED_AS]->(et:EntityType)\n RETURN a, collect(et.name) as entityTypes\n ORDER BY a.created DESC`,\n { resourceId }\n );\n\n return result.records.map(record =>\n parseAnnotationNode(record.get('a'), record.get('entityTypes'))\n );\n } finally {\n await session.close();\n }\n }\n\n async getEntityReferences(resourceId: ResourceId, entityTypes?: string[]): Promise<Annotation[]> {\n const session = this.getSession();\n try {\n let cypher = `MATCH (a:Annotation {resourceId: $resourceId})\n WHERE a.source IS NOT NULL`;\n\n const params: any = { resourceId };\n\n if (entityTypes && entityTypes.length > 0) {\n cypher += `\n MATCH (a)-[:TAGGED_AS]->(et:EntityType)\n WHERE et.name IN $entityTypes`;\n params.entityTypes = entityTypes;\n }\n\n cypher += `\n OPTIONAL MATCH (a)-[:TAGGED_AS]->(et2:EntityType)\n RETURN a, collect(et2.name) as entityTypes\n ORDER BY a.created DESC`;\n\n const result = await session.run(cypher, params);\n\n return result.records.map(record =>\n parseAnnotationNode(record.get('a'), record.get('entityTypes'))\n );\n } finally {\n await session.close();\n }\n }\n\n async getResourceAnnotations(resourceId: ResourceId): Promise<Annotation[]> {\n const session = this.getSession();\n try {\n const result = await session.run(\n `MATCH (a:Annotation {resourceId: $resourceId})\n OPTIONAL MATCH (a)-[:TAGGED_AS]->(et:EntityType)\n RETURN a, collect(et.name) as entityTypes\n ORDER BY a.created DESC`,\n { resourceId }\n );\n\n return result.records.map(record =>\n parseAnnotationNode(record.get('a'), record.get('entityTypes'))\n );\n } finally {\n await session.close();\n }\n }\n\n async getResourceReferencedBy(resourceId: ResourceId, motivation?: string): Promise<Annotation[]> {\n const session = this.getSession();\n try {\n this.logger?.debug('Searching for annotations referencing resource', { resourceId, motivation });\n\n // Build query with optional motivation label filter\n // If motivation is specified, use the label for efficient filtering\n const motivationLabel = motivation ? `:${motivationToLabel(motivation)}` : '';\n const cypher = `MATCH (a:Annotation${motivationLabel})-[:REFERENCES]->(d:Resource {id: $resourceId})\n OPTIONAL MATCH (a)-[:TAGGED_AS]->(et:EntityType)\n RETURN a, collect(et.name) as entityTypes\n ORDER BY a.created DESC`;\n\n const result = await session.run(cypher, { resourceId });\n\n this.logger?.debug('Found annotations', { count: result.records.length });\n\n return result.records.map(record =>\n parseAnnotationNode(record.get('a'), record.get('entityTypes'))\n );\n } finally {\n await session.close();\n }\n }\n\n async getResourceConnections(resourceId: ResourceId): Promise<GraphConnection[]> {\n const session = this.getSession();\n try {\n const result = await session.run(\n `MATCH (d:Resource {id: $resourceId})\n OPTIONAL MATCH (d)<-[:BELONGS_TO]-(a1:Annotation)-[:REFERENCES]->(other:Resource)\n OPTIONAL MATCH (other)<-[:BELONGS_TO]-(a2:Annotation)-[:REFERENCES]->(d)\n WITH other, COLLECT(DISTINCT a1) as outgoing, COLLECT(DISTINCT a2) as incoming\n WHERE other IS NOT NULL\n RETURN other, outgoing, incoming`,\n { resourceId }\n );\n\n const connections: GraphConnection[] = [];\n\n for (const record of result.records) {\n const targetResource = this.parseResourceNode(record.get('other'));\n\n // Fetch entity types for outgoing annotations\n const outgoingNodes = record.get('outgoing');\n const outgoing: Annotation[] = [];\n for (const annNode of outgoingNodes) {\n const annId = annNode.properties.id;\n const annResult = await session.run(\n `MATCH (a:Annotation {id: $id})\n OPTIONAL MATCH (a)-[:TAGGED_AS]->(et:EntityType)\n RETURN a, collect(et.name) as entityTypes`,\n { id: annId }\n );\n if (annResult.records.length > 0) {\n outgoing.push(parseAnnotationNode(\n annResult.records[0]!.get('a'),\n annResult.records[0]!.get('entityTypes')\n ));\n }\n }\n\n // Fetch entity types for incoming annotations\n const incomingNodes = record.get('incoming');\n const incoming: Annotation[] = [];\n for (const annNode of incomingNodes) {\n const annId = annNode.properties.id;\n const annResult = await session.run(\n `MATCH (a:Annotation {id: $id})\n OPTIONAL MATCH (a)-[:TAGGED_AS]->(et:EntityType)\n RETURN a, collect(et.name) as entityTypes`,\n { id: annId }\n );\n if (annResult.records.length > 0) {\n incoming.push(parseAnnotationNode(\n annResult.records[0]!.get('a'),\n annResult.records[0]!.get('entityTypes')\n ));\n }\n }\n\n connections.push({\n targetResource,\n annotations: outgoing,\n bidirectional: incoming.length > 0\n });\n }\n\n return connections;\n } finally {\n await session.close();\n }\n }\n\n async findPath(fromResourceId: string, toResourceId: string, maxDepth: number = 5): Promise<GraphPath[]> {\n const session = this.getSession();\n try {\n const result = await session.run(\n `MATCH path = shortestPath((from:Resource {id: $fromId})-[:REFERENCES*..${maxDepth}]-(to:Resource {id: $toId}))\n WITH path, nodes(path) as docs, relationships(path) as rels\n RETURN docs, rels\n LIMIT 10`,\n { fromId: fromResourceId, toId: toResourceId }\n );\n\n const paths: GraphPath[] = [];\n\n for (const record of result.records) {\n const docs = record.get('docs').map((node: any) => this.parseResourceNode(node));\n const rels = record.get('rels');\n\n // Get annotation details for the relationships\n const annotationIds = rels.map((rel: any) => rel.properties.id).filter((id: any) => id);\n const annotations: Annotation[] = [];\n\n if (annotationIds.length > 0) {\n const selResult = await session.run(\n `MATCH (a:Annotation) WHERE a.id IN $ids\n OPTIONAL MATCH (a)-[:TAGGED_AS]->(et:EntityType)\n RETURN a, collect(et.name) as entityTypes`,\n { ids: annotationIds }\n );\n selResult.records.forEach(rec => {\n annotations.push(parseAnnotationNode(\n rec.get('a'),\n rec.get('entityTypes')\n ));\n });\n }\n\n paths.push({\n resources: docs,\n annotations: annotations\n });\n }\n\n return paths;\n } finally {\n await session.close();\n }\n }\n\n async getEntityTypeStats(): Promise<EntityTypeStats[]> {\n const session = this.getSession();\n try {\n const result = await session.run(\n `MATCH (d:Resource)\n UNWIND d.entityTypes AS type\n RETURN type, count(*) AS count\n ORDER BY count DESC`\n );\n\n return result.records.map(record => ({\n type: record.get('type'),\n count: record.get('count').toNumber()\n }));\n } finally {\n await session.close();\n }\n }\n\n async getStats(): Promise<{\n resourceCount: number;\n annotationCount: number;\n highlightCount: number;\n referenceCount: number;\n entityReferenceCount: number;\n entityTypes: Record<string, number>;\n contentTypes: Record<string, number>;\n }> {\n const session = this.getSession();\n try {\n // Get resource count\n const docCountResult = await session.run('MATCH (d:Resource) RETURN count(d) as count');\n const resourceCount = docCountResult.records[0]!.get('count').toNumber();\n\n // Get annotation counts\n const selCountResult = await session.run('MATCH (a:Annotation) RETURN count(a) as count');\n const annotationCount = selCountResult.records[0]!.get('count').toNumber();\n\n const highlightCountResult = await session.run(\n 'MATCH (a:Annotation) WHERE a.resolvedResourceId IS NULL RETURN count(a) as count'\n );\n const highlightCount = highlightCountResult.records[0]!.get('count').toNumber();\n\n const referenceCountResult = await session.run(\n 'MATCH (a:Annotation) WHERE a.resolvedResourceId IS NOT NULL RETURN count(a) as count'\n );\n const referenceCount = referenceCountResult.records[0]!.get('count').toNumber();\n\n const entityRefCountResult = await session.run(\n 'MATCH (a:Annotation) WHERE a.resolvedResourceId IS NOT NULL AND size(a.entityTypes) > 0 RETURN count(a) as count'\n );\n const entityReferenceCount = entityRefCountResult.records[0]!.get('count').toNumber();\n\n // Get entity type stats\n const entityTypeResult = await session.run(\n `MATCH (d:Resource)\n UNWIND d.entityTypes AS type\n RETURN type, count(*) AS count`\n );\n\n const entityTypes: Record<string, number> = {};\n entityTypeResult.records.forEach(record => {\n entityTypes[record.get('type')] = record.get('count').toNumber();\n });\n\n // Get content type stats\n const contentTypeResult = await session.run(\n `MATCH (d:Resource)\n RETURN d.format as type, count(*) AS count`\n );\n\n const contentTypes: Record<string, number> = {};\n contentTypeResult.records.forEach(record => {\n contentTypes[record.get('type')] = record.get('count').toNumber();\n });\n\n return {\n resourceCount,\n annotationCount,\n highlightCount,\n referenceCount,\n entityReferenceCount,\n entityTypes,\n contentTypes\n };\n } finally {\n await session.close();\n }\n }\n\n async batchCreateResources(resources: ResourceDescriptor[]): Promise<ResourceDescriptor[]> {\n if (resources.length === 0) return [];\n const session = this.getSession();\n try {\n const params = resources.map(resource => {\n const primaryRep = getPrimaryRepresentation(resource);\n if (!primaryRep) throw new Error('Resource must have at least one representation');\n return {\n id: resource['@id'],\n name: resource.name,\n entityTypes: resource.entityTypes,\n format: primaryRep.mediaType,\n archived: resource.archived || false,\n created: resource.dateCreated,\n creator: JSON.stringify(resource.wasAttributedTo),\n contentChecksum: primaryRep.checksum,\n sourceAnnotationId: resource.sourceAnnotationId ?? null,\n sourceResourceId: resource.sourceResourceId ?? null,\n storageUri: getStorageUri(resource) ?? null,\n };\n });\n\n const result = await session.run(\n `UNWIND $resources AS r\n MERGE (d:Resource {id: r.id})\n SET d.name = r.name,\n d.entityTypes = r.entityTypes,\n d.format = r.format,\n d.archived = r.archived,\n d.created = r.created,\n d.creator = r.creator,\n d.contentChecksum = r.contentChecksum,\n d.sourceAnnotationId = r.sourceAnnotationId,\n d.sourceResourceId = r.sourceResourceId,\n d.storageUri = r.storageUri,\n d.stub = false\n RETURN d`,\n { resources: params }\n );\n\n this.logger?.info('Batch created/enriched resources', { count: resources.length });\n return result.records.map(record => this.parseResourceNode(record.get('d')));\n } finally {\n await session.close();\n }\n }\n\n async createAnnotations(inputs: CreateAnnotationInternal[]): Promise<Annotation[]> {\n const results: Annotation[] = [];\n for (const input of inputs) {\n results.push(await this.createAnnotation(input));\n }\n return results;\n }\n\n async resolveReferences(inputs: { annotationId: AnnotationId; source: ResourceId }[]): Promise<Annotation[]> {\n const results: Annotation[] = [];\n for (const input of inputs) {\n results.push(await this.resolveReference(input.annotationId, input.source));\n }\n return results;\n }\n\n async detectAnnotations(_resourceId: ResourceId): Promise<Annotation[]> {\n // This would use AI/ML to detect annotations in a resource\n // For now, return empty array as a placeholder\n return [];\n }\n\n // Tag Collections\n async getEntityTypes(): Promise<string[]> {\n if (this.entityTypesCollection === null) {\n await this.initializeTagCollections();\n }\n return Array.from(this.entityTypesCollection!).sort();\n }\n\n async addEntityType(tag: string): Promise<void> {\n if (this.entityTypesCollection === null) {\n await this.initializeTagCollections();\n }\n this.entityTypesCollection!.add(tag);\n await this.persistTagCollection('entity-types', this.entityTypesCollection!);\n }\n\n async addEntityTypes(tags: string[]): Promise<void> {\n if (this.entityTypesCollection === null) {\n await this.initializeTagCollections();\n }\n tags.forEach(tag => this.entityTypesCollection!.add(tag));\n await this.persistTagCollection('entity-types', this.entityTypesCollection!);\n }\n\n private async initializeTagCollections(): Promise<void> {\n const session = this.getSession();\n try {\n // Load existing collections from Neo4j\n const result = await session.run(\n 'MATCH (t:TagCollection {type: \"entity-types\"}) RETURN t.tags as tags'\n );\n\n let entityTypesFromDb: string[] = [];\n\n if (result.records.length > 0) {\n const record = result.records[0];\n if (record) {\n const tags = record.get('tags');\n entityTypesFromDb = tags || [];\n }\n }\n\n // Load defaults\n const { DEFAULT_ENTITY_TYPES } = await import('@semiont/ontology');\n\n // Merge with defaults\n this.entityTypesCollection = new Set([...DEFAULT_ENTITY_TYPES, ...entityTypesFromDb]);\n\n // Persist merged collection back to Neo4j\n await this.persistTagCollection('entity-types', this.entityTypesCollection);\n } finally {\n await session.close();\n }\n }\n\n private async persistTagCollection(type: string, collection: Set<string>): Promise<void> {\n const session = this.getSession();\n try {\n await session.run(\n 'MERGE (t:TagCollection {type: $type}) SET t.tags = $tags',\n { type, tags: Array.from(collection) }\n );\n } finally {\n await session.close();\n }\n }\n\n generateId(): string {\n return uuidv4().replace(/-/g, '').substring(0, 12);\n }\n\n async clearDatabase(): Promise<void> {\n const session = this.getSession();\n try {\n // CAREFUL! This clears the entire database\n await session.run('MATCH (n) DETACH DELETE n');\n this.entityTypesCollection = null;\n } finally {\n await session.close();\n }\n }\n\n // Helper methods to parse Neo4j nodes\n private parseResourceNode(node: any): ResourceDescriptor {\n const props = node.properties;\n\n // Validate all required fields\n if (!props.id) throw new Error('Resource missing required field: id');\n if (!props.name) throw new Error(`Resource ${props.id} missing required field: name`);\n if (!props.entityTypes) throw new Error(`Resource ${props.id} missing required field: entityTypes`);\n if (!props.format) throw new Error(`Resource ${props.id} missing required field: contentType`);\n if (props.archived === undefined || props.archived === null) throw new Error(`Resource ${props.id} missing required field: archived`);\n if (!props.created) throw new Error(`Resource ${props.id} missing required field: created`);\n if (!props.creator) throw new Error(`Resource ${props.id} missing required field: creator`);\n if (!props.contentChecksum) throw new Error(`Resource ${props.id} missing required field: contentChecksum`);\n\n const resource: ResourceDescriptor = {\n '@context': 'https://schema.org/',\n '@id': props.id,\n name: props.name,\n entityTypes: props.entityTypes,\n representations: [{\n mediaType: props.format,\n checksum: props.contentChecksum,\n rel: 'original',\n storageUri: props.storageUri ?? undefined,\n }],\n archived: props.archived,\n dateCreated: props.created.toString(),\n wasAttributedTo: typeof props.creator === 'string' ? JSON.parse(props.creator) : props.creator,\n };\n\n if (props.sourceResourceId) resource.sourceResourceId = props.sourceResourceId;\n\n return resource;\n }\n\n}\n\n/**\n * Project a neo4j annotation node to the wire `Annotation`.\n *\n * Module-level (not a method) so the projection is unit-testable without a\n * driver: `node` is untyped at this seam, which is exactly how a native\n * neo4j DateTime once reached the wire as `created` unseen by tsc.\n */\nexport function parseAnnotationNode(node: any, entityTypes: string[] = []): Annotation {\n return decodeAnnotation(normalizeProperties(node.properties), entityTypes);\n}\n\n/**\n * Flatten a node's properties to the strings the codec reads.\n *\n * `created` is stored as the codec's own string, so it round-trips verbatim.\n * Rows written before that change hold a native temporal instead, and the\n * driver hands those back as an object whose `toString()` REFORMATS the value\n * (a zero fraction elided, any other padded to nanoseconds) — so a legacy row\n * reads back with a different string than the log carried, until a rebuild\n * replaces it. The coercion\n * that has to happen before the codec sees a value it is entitled to treat\n * as a string. This seam is untyped, so only a test can see it slip.\n */\nfunction normalizeProperties(props: any): AnnotationProperties {\n const normalized: AnnotationProperties = {};\n for (const [key, value] of Object.entries(props ?? {})) {\n if (value === null || value === undefined) continue;\n normalized[key] = typeof value === 'string' ? value : String(value);\n }\n return normalized;\n}\n","// JanusGraph implementation with real Gremlin connection\n// This replaces the mock in-memory implementation\n\nimport { GraphDatabase } from '../interface';\nimport { assertMutableResourceUpdate } from '../interface';\nimport { queryResources } from '../resource-query';\nimport type { Logger } from '@semiont/core';\nimport { resourceId as makeResourceId } from '@semiont/core';\nimport { getBodySource, getPrimaryRepresentation, getResourceId, getStorageUri } from '@semiont/core';\nimport { getEntityTypes } from '@semiont/ontology';\nimport type {\n AnnotationCategory,\n GraphConnection,\n GraphPath,\n EntityTypeStats,\n ResourceFilter,\n UpdateResourceInput,\n CreateAnnotationInternal,\n ResourceId,\n AnnotationId,\n} from '@semiont/core';\nimport { v4 as uuidv4 } from 'uuid';\nimport {\n buildAnnotation,\n decodeAnnotation,\n encodeAnnotation,\n encodeSelector,\n motivationForCategory,\n storedAnnotationType,\n type AnnotationProperties,\n} from '../annotation-codec';\n\nimport type { ResourceDescriptor } from '@semiont/core';\nimport type { Annotation } from '@semiont/core';\n\n/** Helper to get property value from Gremlin vertex properties */\nfunction getPropertyValue(props: any, key: string): any {\n if (!props[key]) return undefined;\n const prop = Array.isArray(props[key]) ? props[key][0] : props[key];\n return prop?.value || prop;\n}\n\n/**\n * Convert a JanusGraph vertex to an Annotation.\n *\n * Module-level so the cross-store conformance suite can run this store's\n * decode path with no live JanusGraph: everything past the flattening is the\n * shared codec's. This is where a missing selector used to become `'{}'` and\n * a missing motivation used to become `'linking'`.\n */\nexport function vertexToAnnotation(vertex: any, entityTypes: string[] = []): Annotation {\n const props = vertex.properties || {};\n const normalized: AnnotationProperties = {};\n for (const key of Object.keys(props)) {\n const value = getPropertyValue(props, key);\n if (value === undefined || value === null) continue;\n normalized[key] = typeof value === 'string' ? value : String(value);\n }\n return decodeAnnotation(normalized, entityTypes);\n}\n\nexport class JanusGraphDatabase implements GraphDatabase {\n private connected: boolean = false;\n private connection: any | null = null;\n private g: any | null = null;\n private logger?: Logger;\n\n // Tag Collections - cached in memory for performance\n private entityTypesCollection: Set<string> | null = null;\n\n\n constructor(\n private graphConfig: {\n host?: string;\n port?: number;\n storageBackend?: 'cassandra' | 'hbase' | 'berkeleydb';\n indexBackend?: 'elasticsearch' | 'solr' | 'lucene';\n logger?: Logger;\n },\n ) {\n this.logger = graphConfig.logger;\n }\n \n async connect(): Promise<void> {\n // Configuration must be provided via constructor\n const host = this.graphConfig.host;\n if (!host) {\n throw new Error('JanusGraph host is required: provide in config');\n }\n\n const port = this.graphConfig.port;\n if (!port) {\n throw new Error('JanusGraph port is required: provide in config');\n }\n\n this.logger?.info('Connecting to JanusGraph', { host, port });\n\n const gremlin = await import('gremlin');\n const DriverRemoteConnection = gremlin.driver.DriverRemoteConnection;\n const traversal = gremlin.process.AnonymousTraversalSource.traversal;\n\n this.connection = new DriverRemoteConnection(\n `ws://${host}:${port}/gremlin`,\n {}\n );\n\n this.g = traversal().withRemote(this.connection);\n\n // Test the connection with a simple query\n await this.g.V().limit(1).toList();\n\n this.connected = true;\n this.logger?.info('Successfully connected to JanusGraph');\n\n // Initialize schema if needed\n await this.initializeSchema();\n }\n \n async disconnect(): Promise<void> {\n if (this.connection) {\n await this.connection.close();\n }\n this.connected = false;\n }\n \n isConnected(): boolean {\n return this.connected;\n }\n \n private async initializeSchema(): Promise<void> {\n // Note: Schema management in JanusGraph typically requires direct access\n // to the management API, which isn't available through Gremlin.\n // In production, you'd run schema initialization scripts separately.\n this.logger?.debug('Schema initialization would happen here in production');\n }\n \n // Helper function to convert vertex to Resource\n private vertexToResource(vertex: any): ResourceDescriptor {\n const props = vertex.properties || {};\n const id = getPropertyValue(props, 'id');\n\n // Validate required fields\n const creatorRaw = getPropertyValue(props, 'creator');\n const contentChecksum = getPropertyValue(props, 'contentChecksum');\n const mediaType = getPropertyValue(props, 'contentType');\n\n if (!creatorRaw) throw new Error(`Resource ${id} missing required field: creator`);\n if (!contentChecksum) throw new Error(`Resource ${id} missing required field: contentChecksum`);\n if (!mediaType) throw new Error(`Resource ${id} missing required field: contentType`);\n\n const creator = typeof creatorRaw === 'string' ? JSON.parse(creatorRaw) : creatorRaw;\n\n const resource: ResourceDescriptor = {\n '@context': 'https://schema.org/',\n '@id': id,\n name: getPropertyValue(props, 'name'),\n entityTypes: JSON.parse(getPropertyValue(props, 'entityTypes') || '[]'),\n representations: [{\n mediaType,\n checksum: contentChecksum,\n rel: 'original',\n storageUri: getPropertyValue(props, 'storageUri') || undefined,\n }],\n archived: getPropertyValue(props, 'archived') === 'true',\n dateCreated: getPropertyValue(props, 'created'),\n wasAttributedTo: creator,\n };\n\n const sourceAnnotationId = getPropertyValue(props, 'sourceAnnotationId');\n const sourceResourceId = getPropertyValue(props, 'sourceResourceId');\n\n if (sourceAnnotationId) resource.sourceAnnotationId = sourceAnnotationId;\n if (sourceResourceId) resource.sourceResourceId = sourceResourceId;\n\n return resource;\n }\n \n // Helper method to fetch annotations with their entity types\n private async fetchAnnotationsWithEntityTypes(annotationVertices: any[]): Promise<Annotation[]> {\n const annotations: Annotation[] = [];\n\n for (const vertex of annotationVertices) {\n const id = getPropertyValue(vertex.properties || {}, 'id');\n\n // Fetch entity types for this annotation\n const entityTypeVertices = await this.g!\n .V()\n .has('Annotation', 'id', id)\n .out('TAGGED_AS')\n .has('EntityType')\n .toList();\n\n const entityTypes = entityTypeVertices.map((v: any) =>\n getPropertyValue(v.properties || {}, 'name')\n ).filter(Boolean);\n\n annotations.push(vertexToAnnotation(vertex, entityTypes));\n }\n\n return annotations;\n }\n\n\n async createResource(resource: ResourceDescriptor): Promise<ResourceDescriptor> {\n const id = getResourceId(resource);\n const primaryRep = getPrimaryRepresentation(resource);\n if (!primaryRep) {\n throw new Error('Resource must have at least one representation');\n }\n\n // Create vertex in JanusGraph using fields from ResourceDescriptor\n const vertex = this.g!\n .addV('Resource')\n .property('id', id)\n .property('name', resource.name)\n .property('entityTypes', JSON.stringify(resource.entityTypes))\n .property('contentType', primaryRep.mediaType)\n .property('archived', resource.archived || false)\n .property('created', resource.dateCreated)\n .property('creator', JSON.stringify(resource.wasAttributedTo))\n .property('contentChecksum', primaryRep.checksum);\n\n if (resource.sourceAnnotationId) {\n vertex.property('sourceAnnotationId', resource.sourceAnnotationId);\n }\n if (resource.sourceResourceId) {\n vertex.property('sourceResourceId', resource.sourceResourceId);\n }\n const storageUri = getStorageUri(resource);\n if (storageUri) {\n vertex.property('storageUri', storageUri);\n }\n\n await vertex.next();\n\n this.logger?.info('Created resource vertex in JanusGraph', { id });\n return resource;\n }\n \n async getResource(id: ResourceId): Promise<ResourceDescriptor | null> {\n const vertices = await this.g!\n .V()\n .has('Resource', 'id', id)\n .toList();\n\n if (vertices.length === 0) {\n return null;\n }\n\n return this.vertexToResource(vertices[0] as any);\n }\n \n async updateResource(id: ResourceId, input: UpdateResourceInput): Promise<ResourceDescriptor> {\n assertMutableResourceUpdate(input);\n\n let traversal = this.g!\n .V()\n .has('Resource', 'id', id);\n if (input.archived !== undefined) {\n traversal = traversal.property('archived', input.archived);\n }\n if (input.entityTypes !== undefined) {\n // Mirrors createResource's storage idiom: entityTypes ride as JSON.\n traversal = traversal.property('entityTypes', JSON.stringify(input.entityTypes));\n }\n await traversal.next();\n\n const updatedResource = await this.getResource(id);\n if (!updatedResource) {\n throw new Error('Resource not found');\n }\n\n return updatedResource;\n }\n \n async deleteResource(id: ResourceId): Promise<void> {\n // Delete the vertex and all its edges\n await this.g!\n .V()\n .has('Resource', 'id', id)\n .drop()\n .next();\n\n this.logger?.info('Deleted resource from JanusGraph', { id });\n }\n \n async listResources(filter: ResourceFilter): Promise<{ resources: ResourceDescriptor[]; total: number }> {\n // Note: filtering is done client-side after retrieval. In production,\n // JanusGraph supports server-side text predicates via Elasticsearch,\n // but composing OR across multiple text properties requires the\n // anonymous-traversal API; for a gateway that's not the production\n // target today, JS post-filtering is simpler and adequate at our scale.\n const docs = await this.g!.V().hasLabel('Resource').toList();\n return queryResources(docs.map((v: any) => this.vertexToResource(v)), filter);\n }\n\n \n async createAnnotation(input: CreateAnnotationInternal): Promise<Annotation> {\n // The caller's id is the system of record's — never mint a fresh one\n // (the event-log id is what deletes and lookups arrive under).\n const annotation = buildAnnotation(input);\n const props = encodeAnnotation(annotation);\n const targetSource = props.resourceId!;\n const bodySource = props.source;\n const entityTypes = getEntityTypes(input);\n\n // Create annotation vertex — every property comes from the codec, so a\n // source-only target contributes no `selector` property at all.\n let vertex = this.g!.addV('Annotation');\n for (const [key, value] of Object.entries(props)) {\n vertex = vertex.property(key, value);\n }\n\n const annVertex = await vertex.next();\n\n // Create edge from annotation to resource (BELONGS_TO)\n await this.g!\n .V(annVertex.value)\n .addE('BELONGS_TO')\n .to(this.g!.V().has('Resource', 'id', targetSource))\n .next();\n\n // If it's a resolved reference, create edge to target resource\n if (bodySource) {\n await this.g!\n .V(annVertex.value)\n .addE('REFERENCES')\n .to(this.g!.V().has('Resource', 'id', bodySource))\n .next();\n }\n\n // Create TAGGED_AS relationships for entity types\n for (const entityType of entityTypes) {\n // Get or create EntityType vertex\n const etResults = await this.g!\n .V()\n .has('EntityType', 'name', entityType)\n .toList();\n\n let etVertex;\n if (etResults.length === 0) {\n // Create new EntityType vertex\n etVertex = await this.g!\n .addV('EntityType')\n .property('name', entityType)\n .next();\n } else {\n etVertex = { value: etResults[0] };\n }\n\n // Create TAGGED_AS edge from Annotation to EntityType\n await this.g!\n .V(annVertex.value)\n .addE('TAGGED_AS')\n .to(this.g!.V(etVertex.value))\n .next();\n }\n\n this.logger?.info('Created annotation in JanusGraph', { id: annotation.id });\n return annotation;\n }\n \n async getAnnotation(id: AnnotationId): Promise<Annotation | null> {\n const vertices = await this.g!\n .V()\n .has('Annotation', 'id', id)\n .toList();\n\n if (vertices.length === 0) {\n return null;\n }\n\n // Fetch entity types from TAGGED_AS relationships\n const entityTypeVertices = await this.g!\n .V()\n .has('Annotation', 'id', id)\n .out('TAGGED_AS')\n .has('EntityType')\n .toList();\n\n const entityTypes = entityTypeVertices.map((v: any) =>\n getPropertyValue(v.properties || {}, 'name')\n ).filter(Boolean);\n\n return vertexToAnnotation(vertices[0] as any, entityTypes);\n }\n \n async updateAnnotation(id: AnnotationId, updates: Partial<Annotation>): Promise<Annotation> {\n const traversalQuery = this.g!\n .V()\n .has('Annotation', 'id', id);\n\n // Update target properties\n if (updates.target !== undefined && typeof updates.target !== 'string') {\n if (updates.target.selector !== undefined) {\n for (const [key, value] of Object.entries(encodeSelector(updates.target.selector))) {\n await traversalQuery.property(key, value).next();\n }\n }\n }\n\n // Update body properties and entity types\n if (updates.body !== undefined) {\n const bodySource = getBodySource(updates.body);\n const entityTypes = getEntityTypes({ body: updates.body });\n\n if (bodySource) {\n await traversalQuery.property('source', bodySource).next();\n }\n\n // Update entity type relationships - remove old ones and create new ones\n if (entityTypes.length >= 0) {\n // Remove existing TAGGED_AS edges\n await this.g!\n .V()\n .has('Annotation', 'id', id)\n .outE('TAGGED_AS')\n .drop()\n .iterate();\n\n // Create new TAGGED_AS edges\n for (const entityType of entityTypes) {\n // Get or create EntityType vertex\n const etResults = await this.g!\n .V()\n .has('EntityType', 'name', entityType)\n .toList();\n\n let etVertex;\n if (etResults.length === 0) {\n // Create new EntityType vertex\n etVertex = await this.g!\n .addV('EntityType')\n .property('name', entityType)\n .next();\n } else {\n etVertex = { value: etResults[0] };\n }\n\n // Create TAGGED_AS edge from Annotation to EntityType\n const annVertices = await this.g!\n .V()\n .has('Annotation', 'id', id)\n .toList();\n\n if (annVertices.length > 0) {\n await this.g!\n .V(annVertices[0])\n .addE('TAGGED_AS')\n .to(this.g!.V(etVertex.value))\n .next();\n }\n }\n }\n }\n\n if (updates.modified !== undefined) {\n await traversalQuery.property('modified', updates.modified).next();\n }\n if (updates.generator !== undefined) {\n await traversalQuery.property('generator', JSON.stringify(updates.generator)).next();\n }\n\n const updatedAnnotation = await this.getAnnotation(id);\n if (!updatedAnnotation) {\n throw new Error('Annotation not found');\n }\n\n return updatedAnnotation;\n }\n \n async deleteAnnotation(id: AnnotationId): Promise<void> {\n await this.g!\n .V()\n .has('Annotation', 'id', id)\n .drop()\n .next();\n\n this.logger?.info('Deleted annotation from JanusGraph', { id });\n }\n \n async listAnnotations(filter: { resourceId?: ResourceId; type?: AnnotationCategory }): Promise<{ annotations: Annotation[]; total: number }> {\n let traversalQuery = this.g!.V().hasLabel('Annotation');\n\n // Apply filters\n if (filter.resourceId) {\n traversalQuery = traversalQuery.has('resourceId', filter.resourceId);\n }\n\n if (filter.type) {\n traversalQuery = traversalQuery.has('type', storedAnnotationType(motivationForCategory(filter.type)));\n }\n\n const vertices = await traversalQuery.toList();\n const annotations = await this.fetchAnnotationsWithEntityTypes(vertices);\n\n return {\n annotations,\n total: annotations.length\n };\n }\n\n async getHighlights(resourceId: ResourceId): Promise<Annotation[]> {\n const { annotations } = await this.listAnnotations({\n resourceId,\n type: 'highlight'\n });\n return annotations;\n }\n\n async resolveReference(annotationId: AnnotationId, source: ResourceId): Promise<Annotation> {\n const annotation = await this.getAnnotation(annotationId);\n if (!annotation) throw new Error('Annotation not found');\n\n // TODO Preserve existing TextualBody entities, add SpecificResource\n // For now, just update with SpecificResource (losing entity tags)\n await this.updateAnnotation(annotationId, {\n body: [\n {\n type: 'SpecificResource',\n source,\n purpose: 'linking' as const,\n },\n ],\n });\n\n // Create edge from annotation to target resource\n await this.g!\n .V()\n .has('Annotation', 'id', annotationId)\n .addE('REFERENCES')\n .to(this.g!.V().has('Resource', 'id', source))\n .next();\n\n const updatedAnnotation = await this.getAnnotation(annotationId);\n if (!updatedAnnotation) {\n throw new Error('Annotation not found after update');\n }\n\n return updatedAnnotation;\n }\n\n async getReferences(resourceId: ResourceId): Promise<Annotation[]> {\n const { annotations } = await this.listAnnotations({\n resourceId,\n type: 'reference'\n });\n return annotations;\n }\n\n async getEntityReferences(resourceId: ResourceId, entityTypes?: string[]): Promise<Annotation[]> {\n const { annotations } = await this.listAnnotations({\n resourceId,\n type: 'reference'\n });\n\n // TODO Extract entity types from body using helper\n if (entityTypes && entityTypes.length > 0) {\n return annotations.filter(ann => {\n const annEntityTypes = getEntityTypes(ann);\n return annEntityTypes.some((type: string) => entityTypes.includes(type));\n });\n }\n\n return annotations.filter(ann => getEntityTypes(ann).length > 0);\n }\n\n async getResourceAnnotations(resourceId: ResourceId): Promise<Annotation[]> {\n const { annotations } = await this.listAnnotations({ resourceId });\n return annotations;\n }\n\n async getResourceReferencedBy(resourceId: ResourceId, _motivation?: string): Promise<Annotation[]> {\n // Find annotations that reference this resource\n const vertices = await this.g!\n .V()\n .hasLabel('Annotation')\n .has('source', resourceId)\n .toList();\n\n return this.fetchAnnotationsWithEntityTypes(vertices);\n }\n \n async getResourceConnections(resourceId: ResourceId): Promise<GraphConnection[]> {\n // Use Gremlin to find connected resources\n const paths = await this.g!\n .V()\n .has('Resource', 'id', resourceId)\n .inE('BELONGS_TO')\n .outV()\n .outE('REFERENCES')\n .inV()\n .path()\n .toList();\n\n // Convert paths to connections\n // This is simplified - real implementation would process paths properly\n this.logger?.debug('Found paths', { count: paths.length });\n\n // For now, also build connections from references\n const connections: GraphConnection[] = [];\n const refs = await this.getReferences(resourceId);\n\n for (const ref of refs) {\n // Extract source from body using helper\n const bodySource = getBodySource(ref.body);\n if (bodySource) {\n const targetDoc = await this.getResource(makeResourceId(bodySource));\n if (targetDoc) {\n const existing = connections.find(c => c.targetResource.id === targetDoc.id);\n if (existing) {\n existing.annotations.push(ref);\n } else {\n connections.push({\n targetResource: targetDoc,\n annotations: [ref],\n relationshipType: undefined,\n bidirectional: false,\n });\n }\n }\n }\n }\n\n return connections;\n }\n \n async findPath(_fromResourceId: string, _toResourceId: string, _maxDepth?: number): Promise<GraphPath[]> {\n // TODO: Implement real graph traversal with JanusGraph\n // For now, return empty array\n return [];\n }\n \n async getEntityTypeStats(): Promise<EntityTypeStats[]> {\n const docs = await this.g!.V().hasLabel('Resource').toList();\n const resources = docs.map((v: any) => this.vertexToResource(v));\n\n const stats = new Map<string, number>();\n\n for (const doc of resources) {\n for (const type of doc.entityTypes || []) {\n stats.set(type, (stats.get(type) || 0) + 1);\n }\n }\n\n return Array.from(stats.entries()).map(([type, count]) => ({ type, count }));\n }\n \n async getStats(): Promise<any> {\n const entityTypes: Record<string, number> = {};\n const contentTypes: Record<string, number> = {};\n\n // Get all resources\n const docs = await this.g!.V().hasLabel('Resource').toList();\n const resources = docs.map((v: any) => this.vertexToResource(v));\n\n for (const doc of resources) {\n for (const type of doc.entityTypes || []) {\n entityTypes[type] = (entityTypes[type] || 0) + 1;\n }\n const primaryRep = getPrimaryRepresentation(doc);\n if (primaryRep?.mediaType) {\n contentTypes[primaryRep.mediaType] = (contentTypes[primaryRep.mediaType] || 0) + 1;\n }\n }\n\n // Get all annotations\n const anns = await this.g!.V().hasLabel('Annotation').toList();\n const annotations = await this.fetchAnnotationsWithEntityTypes(anns);\n\n const highlights = annotations.filter(a => a.motivation === 'highlighting');\n const references = annotations.filter(a => a.motivation === 'linking');\n const entityReferences = references.filter(a => getEntityTypes(a).length > 0);\n\n return {\n resourceCount: resources.length,\n annotationCount: annotations.length,\n highlightCount: highlights.length,\n referenceCount: references.length,\n entityReferenceCount: entityReferences.length,\n entityTypes,\n contentTypes,\n };\n }\n\n async batchCreateResources(resources: ResourceDescriptor[]): Promise<ResourceDescriptor[]> {\n const results: ResourceDescriptor[] = [];\n for (const resource of resources) {\n results.push(await this.createResource(resource));\n }\n return results;\n }\n\n async createAnnotations(inputs: CreateAnnotationInternal[]): Promise<Annotation[]> {\n const results = [];\n for (const input of inputs) {\n results.push(await this.createAnnotation(input));\n }\n return results;\n }\n\n async resolveReferences(inputs: Array<{ annotationId: AnnotationId; source: ResourceId }>): Promise<Annotation[]> {\n const results = [];\n for (const input of inputs) {\n results.push(await this.resolveReference(input.annotationId, input.source));\n }\n return results;\n }\n\n async detectAnnotations(_resourceId: ResourceId): Promise<Annotation[]> {\n // Auto-detection would analyze resource content\n return [];\n }\n \n async getEntityTypes(): Promise<string[]> {\n if (this.entityTypesCollection === null) {\n await this.initializeTagCollections();\n }\n return Array.from(this.entityTypesCollection!).sort();\n }\n \n async addEntityType(tag: string): Promise<void> {\n if (this.entityTypesCollection === null) {\n await this.initializeTagCollections();\n }\n this.entityTypesCollection!.add(tag);\n\n // Persist to JanusGraph\n try {\n // Find or create the TagCollection vertex\n const existing = await this.g!.V()\n .hasLabel('TagCollection')\n .has('type', 'entity-types')\n .toList();\n\n if (existing.length > 0) {\n // Update existing collection\n await this.g!.V(existing[0])\n .property('tags', JSON.stringify(Array.from(this.entityTypesCollection!)))\n .next();\n } else {\n // Create new collection\n await this.g!.addV('TagCollection')\n .property('type', 'entity-types')\n .property('tags', JSON.stringify(Array.from(this.entityTypesCollection!)))\n .next();\n }\n } catch (error) {\n this.logger?.error('Failed to add entity type', { error });\n }\n }\n\n async addEntityTypes(tags: string[]): Promise<void> {\n if (this.entityTypesCollection === null) {\n await this.initializeTagCollections();\n }\n tags.forEach(tag => this.entityTypesCollection!.add(tag));\n\n // Persist all at once\n try {\n const existing = await this.g!.V()\n .hasLabel('TagCollection')\n .has('type', 'entity-types')\n .toList();\n\n if (existing.length > 0) {\n await this.g!.V(existing[0])\n .property('tags', JSON.stringify(Array.from(this.entityTypesCollection!)))\n .next();\n } else {\n await this.g!.addV('TagCollection')\n .property('type', 'entity-types')\n .property('tags', JSON.stringify(Array.from(this.entityTypesCollection!)))\n .next();\n }\n } catch (error) {\n this.logger?.error('Failed to add entity types', { error });\n }\n }\n\n private async initializeTagCollections(): Promise<void> {\n // Load existing collections from JanusGraph\n const collections = await this.g!.V()\n .hasLabel('TagCollection')\n .toList();\n\n let entityTypesFromDb: string[] = [];\n\n for (const vertex of collections) {\n const props = (vertex as any).properties || {};\n const type = getPropertyValue(props, 'type');\n const tagsJson = getPropertyValue(props, 'tags');\n const tags = tagsJson ? JSON.parse(tagsJson) : [];\n\n if (type === 'entity-types') {\n entityTypesFromDb = tags;\n }\n }\n\n // Load defaults\n const { DEFAULT_ENTITY_TYPES } = await import('@semiont/ontology');\n\n // Merge with defaults\n this.entityTypesCollection = new Set([...DEFAULT_ENTITY_TYPES, ...entityTypesFromDb]);\n\n // Persist merged collection back to JanusGraph if it doesn't exist\n if (entityTypesFromDb.length === 0) {\n await this.addEntityTypes([]);\n }\n }\n\n generateId(): string {\n return uuidv4().replace(/-/g, '').substring(0, 12);\n }\n \n async clearDatabase(): Promise<void> {\n // Drop all vertices in JanusGraph\n await this.g!.V().drop().next();\n // Reset cached collections\n this.entityTypesCollection = null;\n this.logger?.info('Cleared JanusGraph database');\n }\n}","// In-memory implementation of GraphDatabase interface\n// Used for development and testing without requiring a real graph database\n\nimport { GraphDatabase } from '../interface';\nimport { assertMutableResourceUpdate } from '../interface';\nimport { queryResources } from '../resource-query';\nimport type { Logger } from '@semiont/core';\nimport type {\n AnnotationCategory,\n GraphConnection,\n GraphPath,\n EntityTypeStats,\n ResourceFilter,\n UpdateResourceInput,\n CreateAnnotationInternal,\n ResourceId,\n AnnotationId,\n} from '@semiont/core';\nimport { resourceId as makeResourceId } from '@semiont/core';\nimport { v4 as uuidv4 } from 'uuid';\nimport { getBodySource, getTargetSource, getResourceId, getPrimaryRepresentation, getResourceEntityTypes } from '@semiont/core';\nimport { getEntityTypes } from '@semiont/ontology';\nimport { buildAnnotation, decodeAnnotation, encodeAnnotation } from '../annotation-codec';\nimport type { ResourceDescriptor } from '@semiont/core';\nimport type { Annotation } from '@semiont/core';\n\n// Simple in-memory storage using Maps\n// Useful for development and testing\n\nexport class MemoryGraphDatabase implements GraphDatabase {\n private connected: boolean = false;\n private logger?: Logger;\n\n // In-memory storage using Maps\n private resources: Map<string, ResourceDescriptor> = new Map();\n private annotations: Map<string, Annotation> = new Map();\n\n constructor(config: { logger?: Logger } = {}) {\n this.logger = config.logger;\n }\n \n async connect(): Promise<void> {\n // No actual connection needed for in-memory storage\n this.logger?.info('Using in-memory graph database');\n this.connected = true;\n }\n \n async disconnect(): Promise<void> {\n // Nothing to close for in-memory storage\n this.connected = false;\n }\n \n isConnected(): boolean {\n return this.connected;\n }\n\n async createResource(resource: ResourceDescriptor): Promise<ResourceDescriptor> {\n const id = getResourceId(resource);\n if (!id) {\n throw new Error('Resource must have an id');\n }\n\n // Simply add to in-memory map\n // await this.client.submit(`\n // graph.tx().rollback()\n // g.addV('Resource')\n // .property('id', id)\n // .property('name', name)\n // .property('entityTypes', entityTypes)\n // .property('contentType', contentType)\n // .property('created', created)\n // .property('updatedAt', updatedAt)\n // graph.tx().commit()\n // `, { id, name, entityTypes, ... });\n\n this.resources.set(id, resource);\n return resource;\n }\n \n async getResource(id: ResourceId): Promise<ResourceDescriptor | null> {\n return this.resources.get(String(id)) || null;\n }\n\n async updateResource(id: ResourceId, input: UpdateResourceInput): Promise<ResourceDescriptor> {\n assertMutableResourceUpdate(input);\n\n const doc = this.resources.get(String(id));\n if (!doc) throw new Error('Resource not found');\n\n if (input.archived !== undefined) doc.archived = input.archived;\n if (input.entityTypes !== undefined) doc.entityTypes = input.entityTypes;\n return doc;\n }\n\n async deleteResource(id: ResourceId): Promise<void> {\n this.resources.delete(String(id));\n\n // Delete annotations targeting or referencing this resource\n const idStr = String(id);\n for (const [selId, sel] of this.annotations) {\n if (getTargetSource(sel.target) === idStr || getBodySource(sel.body) === idStr) {\n this.annotations.delete(selId);\n }\n }\n }\n \n async listResources(filter: ResourceFilter): Promise<{ resources: ResourceDescriptor[]; total: number }> {\n return queryResources(Array.from(this.resources.values()), filter);\n }\n\n \n async createAnnotation(input: CreateAnnotationInternal): Promise<Annotation> {\n // The caller's id is the system of record's — never mint a fresh one\n // (the event-log id is what deletes and lookups arrive under).\n const id = input.id;\n\n // Nothing here needs serializing — but this store is the reference the\n // interface-contract suite runs against, and a reference that cannot\n // exhibit what the real stores exhibit is why four codec divergences\n // survived. So the annotation round-trips through the codec: what a Map\n // hands back is exactly what Cypher and Gremlin hand back.\n const annotation = decodeAnnotation(\n encodeAnnotation(buildAnnotation(input)),\n getEntityTypes(input)\n );\n\n this.annotations.set(id, annotation);\n this.logger?.debug('Created annotation', {\n id,\n motivation: annotation.motivation,\n hasSource: !!getBodySource(annotation.body),\n targetSource: getTargetSource(annotation.target)\n });\n return annotation;\n }\n \n async getAnnotation(id: AnnotationId): Promise<Annotation | null> {\n return this.annotations.get(id) || null;\n }\n \n async updateAnnotation(id: AnnotationId, updates: Partial<Annotation>): Promise<Annotation> {\n const annotation = this.annotations.get(id);\n if (!annotation) throw new Error('Annotation not found');\n\n const updated: Annotation = {\n ...annotation,\n ...updates,\n };\n\n // Motivation should come from updates if provided\n // No need to derive from body type\n\n this.annotations.set(id, updated);\n return updated;\n }\n \n async deleteAnnotation(id: AnnotationId): Promise<void> {\n this.annotations.delete(id);\n }\n \n async listAnnotations(filter: { resourceId?: ResourceId; type?: AnnotationCategory }): Promise<{ annotations: Annotation[]; total: number }> {\n let results = Array.from(this.annotations.values());\n\n if (filter.resourceId) {\n const resourceIdStr = String(filter.resourceId);\n results = results.filter(a => getTargetSource(a.target) === resourceIdStr);\n }\n\n // Only SpecificResource supported, use motivation to distinguish\n if (filter.type) {\n const motivation = filter.type === 'highlight' ? 'highlighting' : 'linking';\n results = results.filter(a => a.motivation === motivation);\n }\n\n return { annotations: results, total: results.length };\n }\n\n async getHighlights(resourceId: ResourceId): Promise<Annotation[]> {\n const resourceIdStr = String(resourceId);\n const highlights = Array.from(this.annotations.values())\n .filter(sel => getTargetSource(sel.target) === resourceIdStr && sel.motivation === 'highlighting');\n this.logger?.debug('Got highlights for resource', { resourceId, count: highlights.length });\n return highlights;\n }\n\n async resolveReference(annotationId: AnnotationId, source: ResourceId): Promise<Annotation> {\n const annotation = this.annotations.get(annotationId);\n if (!annotation) throw new Error('Annotation not found');\n\n // Convert stub (empty array) to resolved SpecificResource\n const updated: Annotation = {\n ...annotation,\n body: {\n type: 'SpecificResource',\n source: String(source),\n purpose: 'linking',\n },\n };\n\n this.annotations.set(annotationId, updated);\n return updated;\n }\n\n async getReferences(resourceId: ResourceId): Promise<Annotation[]> {\n const resourceIdStr = String(resourceId);\n const references = Array.from(this.annotations.values())\n .filter(sel => getTargetSource(sel.target) === resourceIdStr && sel.motivation === 'linking');\n this.logger?.debug('Got references for resource', { resourceId, count: references.length });\n return references;\n }\n\n async getEntityReferences(resourceId: ResourceId, entityTypes?: string[]): Promise<Annotation[]> {\n const resourceIdStr = String(resourceId);\n let refs = Array.from(this.annotations.values())\n .filter(sel => getTargetSource(sel.target) === resourceIdStr && getEntityTypes(sel).length > 0);\n\n if (entityTypes && entityTypes.length > 0) {\n refs = refs.filter(sel => getEntityTypes(sel).some(type => entityTypes.includes(type)));\n }\n\n return refs;\n }\n\n async getResourceAnnotations(resourceId: ResourceId): Promise<Annotation[]> {\n const resourceIdStr = String(resourceId);\n return Array.from(this.annotations.values())\n .filter(sel => getTargetSource(sel.target) === resourceIdStr);\n }\n\n async getResourceReferencedBy(resourceId: ResourceId, _motivation?: string): Promise<Annotation[]> {\n return Array.from(this.annotations.values())\n .filter(sel => getBodySource(sel.body) === String(resourceId));\n }\n\n async getResourceConnections(resourceId: ResourceId): Promise<GraphConnection[]> {\n const connections: GraphConnection[] = [];\n const refs = await this.getReferences(resourceId);\n const resourceIdStr = String(resourceId);\n\n for (const ref of refs) {\n const bodySource = getBodySource(ref.body);\n if (bodySource) {\n const targetDoc = await this.getResource(makeResourceId(bodySource));\n if (targetDoc) {\n const reverseRefs = await this.getReferences(makeResourceId(bodySource));\n const bidirectional = reverseRefs.some(r => getBodySource(r.body) === resourceIdStr);\n\n connections.push({\n targetResource: targetDoc,\n annotations: [ref],\n bidirectional,\n });\n }\n }\n }\n\n return connections;\n }\n\n async findPath(fromResourceId: string, toResourceId: string, maxDepth: number = 5): Promise<GraphPath[]> {\n const visited = new Set<string>();\n const queue: { docId: string; path: ResourceDescriptor[]; sels: Annotation[] }[] = [];\n const fromDoc = await this.getResource(makeResourceId(fromResourceId));\n\n if (!fromDoc) return [];\n\n queue.push({ docId: fromResourceId, path: [fromDoc], sels: [] });\n visited.add(fromResourceId);\n\n const paths: GraphPath[] = [];\n\n while (queue.length > 0 && paths.length < 10) {\n const { docId, path, sels } = queue.shift()!;\n\n if (path.length > maxDepth) continue;\n\n if (docId === toResourceId) {\n paths.push({ resources: path, annotations: sels });\n continue;\n }\n\n const connections = await this.getResourceConnections(makeResourceId(docId));\n\n for (const conn of connections) {\n const targetId = getResourceId(conn.targetResource);\n if (targetId && !visited.has(targetId)) {\n visited.add(targetId);\n queue.push({\n docId: targetId,\n path: [...path, conn.targetResource],\n sels: [...sels, ...conn.annotations],\n });\n }\n }\n }\n\n return paths;\n }\n \n async getEntityTypeStats(): Promise<EntityTypeStats[]> {\n // Simple in-memory statistics\n // const results = await this.client.submit(`\n // g.V().hasLabel('Resource')\n // .values('entityTypes').unfold()\n // .groupCount()\n // `);\n\n const typeCounts = new Map<string, number>();\n\n for (const doc of this.resources.values()) {\n const types = getResourceEntityTypes(doc);\n for (const type of types) {\n typeCounts.set(type, (typeCounts.get(type) || 0) + 1);\n }\n }\n \n return Array.from(typeCounts.entries()).map(([type, count]) => ({\n type,\n count,\n }));\n }\n \n async getStats(): Promise<{\n resourceCount: number;\n annotationCount: number;\n highlightCount: number;\n referenceCount: number;\n entityReferenceCount: number;\n entityTypes: Record<string, number>;\n contentTypes: Record<string, number>;\n }> {\n const entityTypes: Record<string, number> = {};\n const contentTypes: Record<string, number> = {};\n\n for (const doc of this.resources.values()) {\n for (const type of doc.entityTypes || []) {\n entityTypes[type] = (entityTypes[type] || 0) + 1;\n }\n const primaryRep = getPrimaryRepresentation(doc);\n if (primaryRep?.mediaType) {\n contentTypes[primaryRep.mediaType] = (contentTypes[primaryRep.mediaType] || 0) + 1;\n }\n }\n \n const annotations = Array.from(this.annotations.values());\n // Use motivation to distinguish types\n const highlightCount = annotations.filter(a => a.motivation === 'highlighting').length;\n const referenceCount = annotations.filter(a => a.motivation === 'linking').length;\n // Extract entity types from annotation body\n const entityReferenceCount = annotations.filter(\n a => a.motivation === 'linking' && getEntityTypes(a).length > 0\n ).length;\n \n return {\n resourceCount: this.resources.size,\n annotationCount: this.annotations.size,\n highlightCount,\n referenceCount,\n entityReferenceCount,\n entityTypes,\n contentTypes,\n };\n }\n \n async batchCreateResources(resources: ResourceDescriptor[]): Promise<ResourceDescriptor[]> {\n const results: ResourceDescriptor[] = [];\n for (const resource of resources) {\n results.push(await this.createResource(resource));\n }\n return results;\n }\n\n async createAnnotations(inputs: CreateAnnotationInternal[]): Promise<Annotation[]> {\n const results: Annotation[] = [];\n for (const input of inputs) {\n results.push(await this.createAnnotation(input));\n }\n return results;\n }\n \n \n async resolveReferences(inputs: { annotationId: AnnotationId; source: ResourceId }[]): Promise<Annotation[]> {\n const results: Annotation[] = [];\n for (const input of inputs) {\n results.push(await this.resolveReference(input.annotationId, input.source));\n }\n return results;\n }\n \n async detectAnnotations(_resourceId: ResourceId): Promise<Annotation[]> {\n // This would use AI/ML to detect annotations in a resource\n // For now, return empty array as a placeholder\n return [];\n }\n \n // Tag Collections - stored as special vertices in the graph\n private entityTypesCollection: Set<string> | null = null;\n \n async getEntityTypes(): Promise<string[]> {\n // Initialize if not already loaded\n if (this.entityTypesCollection === null) {\n await this.initializeTagCollections();\n }\n return Array.from(this.entityTypesCollection!).sort();\n }\n\n async addEntityType(tag: string): Promise<void> {\n if (this.entityTypesCollection === null) {\n await this.initializeTagCollections();\n }\n this.entityTypesCollection!.add(tag);\n // Simply add to set\n // await this.client.submit(`g.V().has('tagCollection', 'type', 'entity-types')\n // .property(set, 'tags', '${tag}')`, {});\n }\n\n async addEntityTypes(tags: string[]): Promise<void> {\n if (this.entityTypesCollection === null) {\n await this.initializeTagCollections();\n }\n tags.forEach(tag => this.entityTypesCollection!.add(tag));\n // Simply add to set\n }\n \n private async initializeTagCollections(): Promise<void> {\n // Initialize in-memory collections\n // const result = await this.client.submit(\n // `g.V().has('tagCollection', 'type', 'entity-types')\n // .project('type', 'tags').by('type').by('tags')`, {}\n // );\n\n // For now, initialize with defaults if not present\n if (this.entityTypesCollection === null) {\n const { DEFAULT_ENTITY_TYPES } = await import('@semiont/ontology');\n this.entityTypesCollection = new Set(DEFAULT_ENTITY_TYPES);\n }\n }\n \n generateId(): string {\n return uuidv4().replace(/-/g, '').substring(0, 12);\n }\n \n async clearDatabase(): Promise<void> {\n // In production: CAREFUL! This would clear the entire graph\n // await this.client.submit(`g.V().drop()`);\n this.resources.clear();\n this.annotations.clear();\n this.entityTypesCollection = null;\n }\n}","// Factory for creating graph database instances based on configuration\n\nimport { GraphDatabase } from './interface';\nimport { NeptuneGraphDatabase } from './implementations/neptune';\nimport { Neo4jGraphDatabase } from './implementations/neo4j';\nimport { JanusGraphDatabase } from './implementations/janusgraph';\nimport { MemoryGraphDatabase } from './implementations/memorygraph';\nimport type { GraphServiceConfig } from '@semiont/core';\n\nexport type GraphDatabaseType = 'neptune' | 'neo4j' | 'janusgraph' | 'memory';\n\nexport interface GraphDatabaseConfig {\n type: GraphDatabaseType;\n\n // Neptune config\n neptuneEndpoint?: string;\n neptunePort?: number;\n neptuneRegion?: string;\n\n // Neo4j config\n neo4jUri?: string;\n neo4jUsername?: string;\n neo4jPassword?: string;\n neo4jDatabase?: string;\n\n // JanusGraph config\n janusHost?: string;\n janusPort?: number;\n janusStorageBackend?: 'cassandra' | 'hbase' | 'berkeleydb';\n janusIndexBackend?: 'elasticsearch' | 'solr' | 'lucene';\n}\n\n// Singleton instance\nlet graphDatabaseInstance: GraphDatabase | null = null;\n\nexport function createGraphDatabase(config: GraphDatabaseConfig): GraphDatabase {\n switch (config.type) {\n case 'neptune': {\n const neptuneConfig: any = {};\n if (config.neptuneEndpoint !== undefined) neptuneConfig.endpoint = config.neptuneEndpoint;\n if (config.neptunePort !== undefined) neptuneConfig.port = config.neptunePort;\n if (config.neptuneRegion !== undefined) neptuneConfig.region = config.neptuneRegion;\n return new NeptuneGraphDatabase(neptuneConfig);\n }\n\n case 'neo4j': {\n const neo4jConfig: any = {};\n if (config.neo4jUri !== undefined) neo4jConfig.uri = config.neo4jUri;\n if (config.neo4jUsername !== undefined) neo4jConfig.username = config.neo4jUsername;\n if (config.neo4jPassword !== undefined) neo4jConfig.password = config.neo4jPassword;\n if (config.neo4jDatabase !== undefined) neo4jConfig.database = config.neo4jDatabase;\n return new Neo4jGraphDatabase(neo4jConfig);\n }\n\n case 'janusgraph': {\n const janusConfig: any = {};\n if (config.janusHost !== undefined) janusConfig.host = config.janusHost;\n if (config.janusPort !== undefined) janusConfig.port = config.janusPort;\n if (config.janusStorageBackend !== undefined) janusConfig.storageBackend = config.janusStorageBackend;\n if (config.janusIndexBackend !== undefined) janusConfig.indexBackend = config.janusIndexBackend;\n return new JanusGraphDatabase(janusConfig);\n }\n\n case 'memory':\n // Hermetic TEST sink only (WEAVER-ISOLATION D4 refinement): a heap-\n // local graph cannot be shared with a standalone Weaver, so no\n // deployment configures it — and none does. weaver-main refuses it.\n return new MemoryGraphDatabase({});\n\n default:\n throw new Error(`Unsupported graph database type: ${config.type}`);\n }\n}\n\n// Helper function to evaluate environment variable placeholders\nfunction evaluateEnvVar(value: string | undefined): string | undefined {\n if (!value) return undefined;\n\n // Replace ${VAR_NAME} with actual environment variable value\n return value.replace(/\\$\\{([^}]+)\\}/g, (match, varName) => {\n const envValue = process.env[varName];\n if (!envValue) {\n throw new Error(`Environment variable ${varName} is not set. Referenced in configuration as ${match}`);\n }\n return envValue;\n });\n}\n\nexport async function getGraphDatabase(graphConfig: GraphServiceConfig): Promise<GraphDatabase> {\n if (!graphDatabaseInstance) {\n const config: GraphDatabaseConfig = {\n type: graphConfig.type,\n };\n\n // Apply configuration based on type\n if (graphConfig.type === 'janusgraph') {\n if (graphConfig.host) {\n config.janusHost = graphConfig.host;\n }\n if (graphConfig.port) {\n config.janusPort = graphConfig.port;\n }\n if (graphConfig.storage) {\n config.janusStorageBackend = graphConfig.storage as any;\n }\n if (graphConfig.index && graphConfig.index !== 'none') {\n config.janusIndexBackend = graphConfig.index as any;\n }\n } else if (graphConfig.type === 'neptune') {\n if (graphConfig.endpoint) {\n config.neptuneEndpoint = graphConfig.endpoint;\n }\n if (graphConfig.port) {\n config.neptunePort = graphConfig.port;\n }\n if (graphConfig.region) {\n config.neptuneRegion = graphConfig.region;\n }\n } else if (graphConfig.type === 'neo4j') {\n if (graphConfig.uri) {\n config.neo4jUri = evaluateEnvVar(graphConfig.uri);\n }\n if (graphConfig.username) {\n config.neo4jUsername = evaluateEnvVar(graphConfig.username);\n }\n if (graphConfig.password) {\n config.neo4jPassword = evaluateEnvVar(graphConfig.password);\n }\n if (graphConfig.database) {\n config.neo4jDatabase = evaluateEnvVar(graphConfig.database);\n }\n }\n\n graphDatabaseInstance = createGraphDatabase(config);\n await graphDatabaseInstance.connect();\n }\n\n if (!graphDatabaseInstance.isConnected()) {\n await graphDatabaseInstance.connect();\n }\n\n return graphDatabaseInstance;\n}\n\nexport async function closeGraphDatabase(): Promise<void> {\n if (graphDatabaseInstance) {\n await graphDatabaseInstance.disconnect();\n graphDatabaseInstance = null;\n }\n}"],"mappings":"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","names":["getEntityTypes","getBodySource","getTargetSource","getStorageUri","process","getEntityTypes","entityTypes","targetDocId","uuidv4","getPrimaryRepresentation","getStorageUri","getEntityTypes","getPrimaryRepresentation","getStorageUri","getEntityTypes","uuidv4","normalizeProperties","getBodySource","getPrimaryRepresentation","getResourceId","getStorageUri","getEntityTypes","uuidv4","vertexToAnnotation","gremlin","getResourceId","getPrimaryRepresentation","getStorageUri","getEntityTypes","getBodySource","uuidv4","makeResourceId","uuidv4","getBodySource","getTargetSource","getResourceId","getPrimaryRepresentation","getResourceEntityTypes","getEntityTypes","getResourceId","getTargetSource","getBodySource","getEntityTypes","makeResourceId","getResourceEntityTypes","getPrimaryRepresentation","uuidv4"]}
|