@lucern/graph-sync 1.0.31 → 1.0.33

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.
@@ -4,12 +4,12 @@ declare const DUAL_WRITE_EDGE_TYPES: readonly ["supports", "informs", "tests", "
4
4
  type DualWriteEdgeType = (typeof DUAL_WRITE_EDGE_TYPES)[number];
5
5
  declare function needsDualWrite(edgeType: string): boolean;
6
6
  declare const createEdge: convex_server.RegisteredAction<"internal", {
7
- tenantId?: string | undefined;
8
- topicId?: string | undefined;
9
7
  weight?: number | undefined;
10
8
  confidence?: number | undefined;
11
9
  context?: string | undefined;
12
10
  derivationType?: string | undefined;
11
+ topicId?: string | undefined;
12
+ tenantId?: string | undefined;
13
13
  workspaceId?: string | undefined;
14
14
  fromLayer?: string | undefined;
15
15
  toLayer?: string | undefined;
@@ -22,10 +22,10 @@ declare const createEdge: convex_server.RegisteredAction<"internal", {
22
22
  validUntil?: number | undefined;
23
23
  metadata?: any;
24
24
  globalId: string;
25
- fromGlobalId: string;
26
- toGlobalId: string;
27
25
  edgeType: string;
28
26
  createdBy: string;
27
+ fromGlobalId: string;
28
+ toGlobalId: string;
29
29
  }, Promise<{
30
30
  success: boolean;
31
31
  globalId: string;
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/convex.ts","../src/neo4jDriver.ts","../src/neo4jEdgeAPI.ts"],"names":["v"],"mappings":"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","file":"neo4jEdgeAPI.js","sourcesContent":["import { unsafeConvexAnyApi } from \"@lucern/contracts/convex/unsafeAnyApi\";\nimport {\n type ActionBuilder,\n actionGeneric,\n type GenericActionCtx,\n type GenericDataModel,\n type GenericDocument,\n type GenericMutationCtx,\n type GenericQueryCtx,\n internalActionGeneric,\n internalMutationGeneric,\n internalQueryGeneric,\n type MutationBuilder,\n type QueryBuilder,\n} from \"convex/server\";\nimport type { GenericId, Value } from \"convex/values\";\n\nexport const internal = unsafeConvexAnyApi(\n \"graph-sync top-level module bundle lacks a committed Convex _generated/api surface\"\n);\n\ntype TableNames = string;\nexport type Id<TableName extends TableNames = string> = GenericId<TableName>;\ntype GraphSyncDocument<TableName extends string> = GenericDocument & {\n _creationTime: number;\n _id: GenericId<TableName>;\n};\n\ninterface GraphSyncTableInfo<\n Document extends GenericDocument,\n Indexes extends Record<string, string[]>,\n> {\n document: Document;\n fieldPaths: string;\n indexes: Indexes;\n searchIndexes: Record<string, never>;\n vectorIndexes: Record<string, never>;\n}\n\ntype EpistemicNodeDocument = GraphSyncDocument<\"epistemicNodes\"> & {\n globalId: string;\n nodeType: string;\n projectId?: string;\n updatedAt?: number;\n};\n\ntype EpistemicNodeEmbeddingDocument =\n GraphSyncDocument<\"epistemicNodeEmbeddings\"> & {\n embedding?: number[];\n nodeId: GenericId<\"epistemicNodes\">;\n };\n\ntype EpistemicEdgeDocument = GraphSyncDocument<\"epistemicEdges\"> & {\n edgeType: string;\n fromNodeId?: GenericId<\"epistemicNodes\"> | null;\n globalId?: string;\n sourceGlobalId?: string;\n targetGlobalId?: string;\n toNodeId?: GenericId<\"epistemicNodes\"> | null;\n};\n\ntype Neo4jSyncQueueDocument = GraphSyncDocument<\"neo4jSyncQueue\"> & {\n attempts?: number;\n createdAt?: number;\n entityId: string;\n entityType: \"node\" | \"edge\";\n lastAttemptAt?: number;\n lastError?: string;\n maxAttempts?: number;\n operation: \"upsert\" | \"delete\";\n status: \"pending\" | \"in_progress\" | \"failed\" | \"succeeded\";\n updatedAt?: number;\n};\n\ninterface GraphSyncDataModel extends GenericDataModel {\n epistemicEdges: GraphSyncTableInfo<\n EpistemicEdgeDocument,\n {\n by_globalId: [\"globalId\"];\n }\n >;\n epistemicNodeEmbeddings: GraphSyncTableInfo<\n EpistemicNodeEmbeddingDocument,\n {\n by_nodeId: [\"nodeId\"];\n }\n >;\n epistemicNodes: GraphSyncTableInfo<\n EpistemicNodeDocument,\n {\n by_nodeType: [\"nodeType\"];\n }\n >;\n neo4jSyncQueue: GraphSyncTableInfo<\n Neo4jSyncQueueDocument,\n {\n by_entity: [\"entityType\", \"entityId\"];\n by_status: [\"status\"];\n }\n >;\n}\n\nexport type GraphSyncRecord = Record<string, Value>;\nexport type ActionCtx = GenericActionCtx<GraphSyncDataModel>;\nexport type MutationCtx = GenericMutationCtx<GraphSyncDataModel>;\nexport type QueryCtx = GenericQueryCtx<GraphSyncDataModel>;\n\nexport const action = actionGeneric as ActionBuilder<\n GraphSyncDataModel,\n \"public\"\n>;\nexport const internalAction = internalActionGeneric as ActionBuilder<\n GraphSyncDataModel,\n \"internal\"\n>;\nexport const internalMutation = internalMutationGeneric as MutationBuilder<\n GraphSyncDataModel,\n \"internal\"\n>;\nexport const internalQuery = internalQueryGeneric as QueryBuilder<\n GraphSyncDataModel,\n \"internal\"\n>;\n","// biome-ignore-all lint/style/useFilenamingConvention: Published @lucern/graph-sync/neo4jDriver subpath; rename needs an export-map migration.\n/**\n * neo4jDriver module implementation.\n */\n\n\"use node\";\n/**\n * Direct Neo4j Driver for Convex\n *\n * Uses the \"use node\" directive to enable Node.js runtime, allowing\n * direct use of the neo4j-driver package instead of HTTP proxies.\n *\n * Environment Variables (set per deployment via `npx convex env set`):\n * - NEO4J_URI: neo4j+s://xxx.databases.neo4j.io\n * - NEO4J_USER: neo4j\n * - NEO4J_PASSWORD: your-password\n *\n * @see /docs/architecture/UNIFIED_GRAPH_ARCHITECTURE.md\n */\n\nimport neo4j, { type Driver } from \"neo4j-driver\";\n\n// =============================================================================\n// VALID LABELS AND RELATIONSHIP TYPES (Security: Prevent Cypher Injection)\n// =============================================================================\n\nconst VALID_NODE_LABELS = new Set([\n // Ontological\n \"ValueChain\",\n \"Function\",\n \"FinSector\",\n \"Company\",\n \"Person\",\n \"Investor\",\n // Epistemic\n \"Theme\",\n \"Belief\",\n \"Question\",\n \"Evidence\",\n \"Source\",\n \"Decision\",\n \"Sprint\",\n \"Claim\",\n \"Synthesis\",\n \"Answer\",\n]);\n\nconst VALID_RELATIONSHIP_TYPES = new Set([\n // Cross-layer edges\n \"EXTRACTED_FROM\",\n \"ANSWERS\",\n \"RESPONDS_TO\",\n \"INFORMS\",\n \"QUALIFIES\",\n \"TESTS\",\n \"EXPLORES\",\n \"BASED_ON\",\n \"RELATES_TO_THESIS\",\n \"BELONGS_TO\",\n \"PLAYS_THEME\",\n // Same-layer edges\n \"SUPERSEDES\",\n \"SAME_AS\",\n \"DEPENDS_ON\",\n \"REINFORCES\",\n \"PARENT_OF\",\n \"CHILD_OF\",\n \"FALSIFIED_BY\",\n \"EXCLUSIVE_WITH\",\n \"COLLAPSES_IF\",\n \"CASCADE_FROM\",\n \"STRENGTHENED_BY\",\n \"WEAKENED_BY\",\n \"ALTERNATIVE_TO\",\n \"SUBSUMES\",\n \"VALIDATED_BY\",\n \"REQUIRED_FOR\",\n \"PREREQUISITE_FOR\",\n \"PARALLEL_TO\",\n \"CORROBORATES\",\n \"EXTENDS\",\n \"SAME_SOURCE_AS\",\n \"SAME_THEME_AS\",\n // Ontological\n \"EVALUATES\",\n \"PERSPECTIVE_ON\",\n \"WORKS_AT\",\n \"PARTICIPATES_IN\",\n \"PERFORMS\",\n \"FUNCTION_IN\",\n \"IMPACTS\",\n \"INVESTED_IN\",\n \"RAISED_FROM\",\n \"BASED_ON_BELIEF\",\n \"BASED_ON_QUESTION\",\n \"BLOCKED_BY_CONTRADICTION\",\n \"INFORMED_BY_THEME\",\n]);\n\nexport function validateLabel(label: string): void {\n if (!VALID_NODE_LABELS.has(label)) {\n throw new Error(\n `[Neo4j Security] Invalid node label: ${label}. Must be one of: ${Array.from(VALID_NODE_LABELS).join(\", \")}`\n );\n }\n}\n\nexport function validateRelType(relType: string): void {\n if (!VALID_RELATIONSHIP_TYPES.has(relType)) {\n throw new Error(\n `[Neo4j Security] Invalid relationship type: ${relType}. Must be one of: ${Array.from(VALID_RELATIONSHIP_TYPES).join(\", \")}`\n );\n }\n}\n\n// =============================================================================\n// DRIVER SINGLETON\n// =============================================================================\n\nlet driver: Driver | null = null;\n\nfunction getDriver(): Driver {\n if (!driver) {\n const uri = process.env.NEO4J_URI;\n const user = process.env.NEO4J_USER;\n const password = process.env.NEO4J_PASSWORD;\n\n if (!(uri && user && password)) {\n throw new Error(\n \"[Neo4j Driver] Missing credentials. Set NEO4J_URI, NEO4J_USER, NEO4J_PASSWORD via `npx convex env set`\"\n );\n }\n\n driver = neo4j.driver(uri, neo4j.auth.basic(user, password), {\n // Connection pool settings\n maxConnectionPoolSize: 50,\n connectionAcquisitionTimeout: 30_000,\n // Logging\n logging: {\n level: \"warn\",\n logger: (level, message) => console.log(`[Neo4j ${level}] ${message}`),\n },\n });\n }\n return driver;\n}\n\n// =============================================================================\n// QUERY CONFIGURATION\n// =============================================================================\n\n/**\n * Default query timeout in milliseconds.\n * Prevents expensive graph traversals from hanging indefinitely.\n */\nexport const DEFAULT_QUERY_TIMEOUT_MS = 30_000; // 30 seconds\n\n/**\n * Timeout for complex graph queries (cascade simulation, lineage traversal)\n */\nexport const COMPLEX_QUERY_TIMEOUT_MS = 60_000; // 60 seconds\n\n// =============================================================================\n// QUERY EXECUTION\n// =============================================================================\n\n/**\n * Convert JavaScript values to Neo4j-compatible types\n * Neo4j requires explicit integers, not floats\n */\nfunction toNeo4jParams(\n params: Record<string, unknown>\n): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(params)) {\n if (typeof value === \"number\" && Number.isInteger(value)) {\n // Convert JavaScript integers to Neo4j integers\n result[key] = neo4j.int(value);\n } else if (Array.isArray(value)) {\n result[key] = value.map((v) =>\n typeof v === \"number\" && Number.isInteger(v) ? neo4j.int(v) : v\n );\n } else {\n result[key] = value;\n }\n }\n return result;\n}\n\n/**\n * Execute a Cypher query and return results as typed objects\n *\n * @param query - Cypher query string\n * @param params - Query parameters\n * @param timeoutMs - Query timeout in milliseconds (default: 30s)\n */\nexport async function runCypher<T = Record<string, unknown>>(\n query: string,\n params: Record<string, unknown> = {},\n timeoutMs: number = DEFAULT_QUERY_TIMEOUT_MS\n): Promise<T[]> {\n const neo4jDriver = getDriver();\n const session = neo4jDriver.session();\n\n try {\n const neo4jParams = toNeo4jParams(params);\n const result = await session.run(query, neo4jParams, {\n timeout: neo4j.int(timeoutMs),\n });\n return result.records.map((record) => {\n const obj: Record<string, unknown> = {};\n for (const key of record.keys) {\n const field = String(key);\n obj[field] = convertNeo4jValue(record.get(field));\n }\n return obj as T;\n });\n } finally {\n await session.close();\n }\n}\n\n/**\n * Execute a write transaction (for mutations)\n *\n * @param query - Cypher query string\n * @param params - Query parameters\n * @param timeoutMs - Transaction timeout in milliseconds (default: 30s)\n */\nexport async function runWriteTransaction<T = Record<string, unknown>>(\n query: string,\n params: Record<string, unknown> = {},\n timeoutMs: number = DEFAULT_QUERY_TIMEOUT_MS\n): Promise<T[]> {\n const neo4jDriver = getDriver();\n const session = neo4jDriver.session();\n\n try {\n const neo4jParams = toNeo4jParams(params);\n const result = await session.executeWrite(\n async (tx) => await tx.run(query, neo4jParams),\n { timeout: timeoutMs }\n );\n return result.records.map((record) => {\n const obj: Record<string, unknown> = {};\n for (const key of record.keys) {\n const field = String(key);\n obj[field] = convertNeo4jValue(record.get(field));\n }\n return obj as T;\n });\n } finally {\n await session.close();\n }\n}\n\n/**\n * Execute multiple queries in a single transaction\n *\n * @param queries - Array of queries with parameters\n * @param timeoutMs - Transaction timeout in milliseconds (default: 60s for batch)\n */\nexport async function runBatchTransaction(\n queries: Array<{ query: string; params: Record<string, unknown> }>,\n timeoutMs: number = COMPLEX_QUERY_TIMEOUT_MS\n): Promise<void> {\n const neo4jDriver = getDriver();\n const session = neo4jDriver.session();\n\n try {\n await session.executeWrite(\n async (tx) => {\n for (const { query, params } of queries) {\n await tx.run(query, params);\n }\n },\n { timeout: timeoutMs }\n );\n } finally {\n await session.close();\n }\n}\n\n// =============================================================================\n// NODE OPERATIONS\n// =============================================================================\n\n/**\n * Upsert a node by globalId\n */\nexport async function upsertNode(\n label: string,\n globalId: string,\n properties: Record<string, unknown>\n): Promise<void> {\n validateLabel(label); // Security: prevent Cypher injection\n await runWriteTransaction(\n `\n MERGE (n:${label} {globalId: $globalId})\n SET n += $properties\n SET n.updatedAt = timestamp()\n `,\n { globalId, properties }\n );\n}\n\n/**\n * Delete a node by globalId\n */\nexport async function deleteNode(globalId: string): Promise<void> {\n await runWriteTransaction(\n `\n MATCH (n {globalId: $globalId})\n DETACH DELETE n\n `,\n { globalId }\n );\n}\n\n/**\n * Batch upsert nodes\n */\nexport async function batchUpsertNodes(\n label: string,\n nodes: Array<{ globalId: string; properties: Record<string, unknown> }>\n): Promise<void> {\n if (nodes.length === 0) {\n return;\n }\n\n validateLabel(label); // Security: prevent Cypher injection\n await runWriteTransaction(\n `\n UNWIND $nodes as node\n MERGE (n:${label} {globalId: node.globalId})\n SET n += node.properties\n SET n.updatedAt = timestamp()\n `,\n { nodes }\n );\n}\n\n// =============================================================================\n// EDGE OPERATIONS\n// =============================================================================\n\n/**\n * Upsert an edge by globalId\n */\nexport async function upsertEdge(\n relType: string,\n globalId: string,\n fromGlobalId: string,\n toGlobalId: string,\n properties: Record<string, unknown> = {}\n): Promise<void> {\n validateRelType(relType); // Security: prevent Cypher injection\n await runWriteTransaction(\n `\n MATCH (from {globalId: $fromGlobalId})\n MATCH (to {globalId: $toGlobalId})\n MERGE (from)-[r:${relType} {globalId: $globalId}]->(to)\n SET r += $properties\n SET r.updatedAt = timestamp()\n `,\n { globalId, fromGlobalId, toGlobalId, properties }\n );\n}\n\n/**\n * Delete an edge by globalId\n */\nexport async function deleteEdge(globalId: string): Promise<void> {\n await runWriteTransaction(\n `\n MATCH ()-[r {globalId: $globalId}]->()\n DELETE r\n `,\n { globalId }\n );\n}\n\n/**\n * Batch upsert edges\n */\nexport async function batchUpsertEdges(\n edges: Array<{\n relType: string;\n globalId: string;\n fromGlobalId: string;\n toGlobalId: string;\n properties?: Record<string, unknown>;\n }>\n): Promise<void> {\n if (edges.length === 0) {\n return;\n }\n\n // Group by relationship type for efficient batching\n const byType = new Map<string, typeof edges>();\n for (const edge of edges) {\n const existing = byType.get(edge.relType) || [];\n existing.push(edge);\n byType.set(edge.relType, existing);\n }\n\n const queries: Array<{ query: string; params: Record<string, unknown> }> = [];\n for (const [relType, typeEdges] of byType) {\n queries.push({\n query: `\n UNWIND $edges as edge\n MATCH (from {globalId: edge.fromGlobalId})\n MATCH (to {globalId: edge.toGlobalId})\n MERGE (from)-[r:${relType} {globalId: edge.globalId}]->(to)\n SET r += edge.properties\n SET r.updatedAt = timestamp()\n `,\n params: {\n edges: typeEdges.map((e) => ({\n globalId: e.globalId,\n fromGlobalId: e.fromGlobalId,\n toGlobalId: e.toGlobalId,\n properties: e.properties || {},\n })),\n },\n });\n }\n\n await runBatchTransaction(queries);\n}\n\n// =============================================================================\n// HEALTH CHECK\n// =============================================================================\n\n/**\n * Check if Neo4j connection is healthy\n */\nexport async function healthCheck(): Promise<{\n healthy: boolean;\n nodeCount?: number;\n error?: string;\n}> {\n try {\n const result = await runCypher<{ count: number }>(\n \"MATCH (n) RETURN count(n) as count LIMIT 1\"\n );\n return {\n healthy: true,\n nodeCount: result[0]?.count || 0,\n };\n } catch (error) {\n return {\n healthy: false,\n error: error instanceof Error ? error.message : \"Unknown error\",\n };\n }\n}\n\n/**\n * Get connection info (for debugging)\n */\nexport function getConnectionInfo(): {\n uri: string | undefined;\n user: string | undefined;\n configured: boolean;\n} {\n return {\n uri: process.env.NEO4J_URI,\n user: process.env.NEO4J_USER,\n configured: Boolean(\n process.env.NEO4J_URI &&\n process.env.NEO4J_USER &&\n process.env.NEO4J_PASSWORD\n ),\n };\n}\n\n// =============================================================================\n// VALUE CONVERSION\n// =============================================================================\n\n/**\n * Convert Neo4j types to plain JavaScript\n */\nfunction convertNeo4jValue(value: unknown): unknown {\n if (value === null || value === undefined) {\n return null;\n }\n\n // Handle Neo4j Integer\n if (neo4j.isInt(value)) {\n return neo4j.integer.toNumber(value);\n }\n\n // Handle Neo4j Date/Time types\n if (neo4j.isDate(value) || neo4j.isDateTime(value) || neo4j.isTime(value)) {\n return value.toString();\n }\n\n // Handle arrays\n if (Array.isArray(value)) {\n return value.map(convertNeo4jValue);\n }\n\n // Handle Node objects\n if (value && typeof value === \"object\" && \"properties\" in value) {\n const nodeObj = value as { properties: Record<string, unknown> };\n const result: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(nodeObj.properties)) {\n result[k] = convertNeo4jValue(v);\n }\n return result;\n }\n\n // Handle plain objects\n if (typeof value === \"object\") {\n const result: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(value as Record<string, unknown>)) {\n result[k] = convertNeo4jValue(v);\n }\n return result;\n }\n\n return value;\n}\n\n// =============================================================================\n// CLEANUP\n// =============================================================================\n\n/**\n * Close the driver connection (for graceful shutdown)\n */\nexport async function closeDriver(): Promise<void> {\n if (driver) {\n await driver.close();\n driver = null;\n }\n}\n","// biome-ignore-all lint/style/useFilenamingConvention: Published @lucern/graph-sync/neo4jEdgeAPI subpath; rename needs an export-map migration.\n\"use node\";\n\n/**\n * Neo4j edge API host actions.\n *\n * The reasoning kernel schedules these actions through the tenant Convex host\n * when optional graph mirroring is installed. Neo4j remains authoritative for\n * traversal topology; Convex mirrors selected edge types for realtime reads.\n */\n\nimport { permissiveReturn } from \"@lucern/contracts/schema-helpers/validators\";\nimport { getNeo4jRelType } from \"@lucern/graph-primitives/graphTypes\";\nimport { v } from \"convex/values\";\nimport { internal, internalAction } from \"./convex\";\nimport {\n getConnectionInfo,\n runCypher,\n runWriteTransaction,\n} from \"./neo4jDriver\";\n\nexport const DUAL_WRITE_EDGE_TYPES = [\n \"supports\",\n \"informs\",\n \"tests\",\n \"depends_on\",\n \"derived_from\",\n \"contains\",\n \"supersedes\",\n \"extracted_from\",\n \"responds_to\",\n \"based_on\",\n \"answers\",\n \"belongs_to\",\n \"relates_to_thesis\",\n \"corroborates\",\n \"extends\",\n \"same_source_as\",\n \"same_theme_as\",\n \"plays_theme\",\n \"impacts\",\n \"evaluates\",\n \"mentioned_in\",\n \"perspective_on\",\n] as const;\n\nexport type DualWriteEdgeType = (typeof DUAL_WRITE_EDGE_TYPES)[number];\nconst LOWER_EDGE_TYPE_REGEX = /^[a-z0-9_]+$/u;\nconst UPPER_EDGE_TYPE_REGEX = /^[A-Z0-9_]+$/u;\n\ninterface EdgeActionCtx {\n runMutation<Result = unknown>(\n functionReference: unknown,\n args?: unknown\n ): Promise<Result>;\n}\n\ninterface CreateEdgeInput {\n confidence?: number;\n context?: string;\n createdBy: string;\n derivationType?: string;\n edgeType: string;\n fromGlobalId: string;\n fromLayer?: string;\n fromNodeType?: string;\n globalId: string;\n logicalRole?: string;\n metadata?: unknown;\n reasoningMethod?: string;\n temporalClass?: string;\n tenantId?: string;\n toGlobalId: string;\n toLayer?: string;\n toNodeType?: string;\n topicId?: string;\n validFrom?: number;\n validUntil?: number;\n weight?: number;\n workspaceId?: string;\n}\n\ninterface MirrorEdgeInput {\n confidence?: number;\n context?: string;\n createdBy: string;\n derivationType?: string;\n edgeType: string;\n fromGlobalId: string;\n fromLayer?: string;\n fromNodeType?: string;\n globalId: string;\n logicalRole?: string;\n reasoningMethod?: string;\n temporalClass?: string;\n toGlobalId: string;\n toLayer?: string;\n toNodeType?: string;\n topicId?: string;\n validFrom?: number;\n validUntil?: number;\n weight?: number;\n}\n\nexport function needsDualWrite(edgeType: string): boolean {\n return DUAL_WRITE_EDGE_TYPES.includes(edgeType as DualWriteEdgeType);\n}\n\nfunction normalizeEdgeType(edgeType: string): string {\n const normalized = edgeType.trim().toLowerCase();\n if (!LOWER_EDGE_TYPE_REGEX.test(normalized)) {\n throw new Error(`[Neo4j Edge API] Invalid edge type: ${edgeType}`);\n }\n return normalized;\n}\n\nfunction resolveRelationshipType(edgeType: string): string {\n const relType = getNeo4jRelType(edgeType);\n if (!UPPER_EDGE_TYPE_REGEX.test(relType)) {\n throw new Error(`[Neo4j Edge API] Invalid relationship type: ${relType}`);\n }\n return relType;\n}\n\nfunction readStringProperty(\n source: Record<string, unknown> | undefined,\n key: string\n): string | undefined {\n const value = source?.[key];\n return typeof value === \"string\" && value.trim().length > 0\n ? value.trim()\n : undefined;\n}\n\nfunction readNumberProperty(\n source: Record<string, unknown> | undefined,\n key: string\n): number | undefined {\n const value = source?.[key];\n return typeof value === \"number\" && Number.isFinite(value)\n ? value\n : undefined;\n}\n\nfunction metadataSummary(\n metadata: Record<string, unknown> | undefined\n): string | undefined {\n if (!metadata) {\n return;\n }\n\n return Object.entries(metadata)\n .map(([key, value]) => `${key}=${String(value)}`)\n .slice(0, 8)\n .join(\" | \");\n}\n\nfunction readMetadata(metadata: unknown): Record<string, unknown> | undefined {\n return metadata && typeof metadata === \"object\" && !Array.isArray(metadata)\n ? (metadata as Record<string, unknown>)\n : undefined;\n}\n\nfunction neo4jEdgeProperties(\n args: CreateEdgeInput,\n edgeType: string,\n metadata: Record<string, unknown> | undefined,\n now: number\n): Record<string, unknown> {\n return {\n globalId: args.globalId,\n edgeType,\n weight: args.weight ?? 1,\n confidence:\n args.confidence ?? readNumberProperty(metadata, \"confidence\") ?? 1,\n context: args.context ?? metadataSummary(metadata) ?? \"\",\n derivationType: args.derivationType ?? \"\",\n createdBy: args.createdBy,\n createdAt: now,\n updatedAt: now,\n topicId: args.topicId ?? readStringProperty(metadata, \"topicId\") ?? \"\",\n tenantId: args.tenantId ?? readStringProperty(metadata, \"tenantId\") ?? \"\",\n workspaceId:\n args.workspaceId ?? readStringProperty(metadata, \"workspaceId\") ?? \"\",\n fromLayer: args.fromLayer ?? \"\",\n toLayer: args.toLayer ?? \"\",\n fromNodeType: args.fromNodeType ?? \"\",\n toNodeType: args.toNodeType ?? \"\",\n reasoningMethod: args.reasoningMethod ?? \"\",\n logicalRole: args.logicalRole ?? \"\",\n temporalClass: args.temporalClass ?? \"structural\",\n validFrom: args.validFrom ?? now,\n validUntil: args.validUntil ?? null,\n };\n}\n\nfunction mirrorInputFromCreateArgs(\n args: CreateEdgeInput,\n edgeType: string\n): MirrorEdgeInput {\n return {\n globalId: args.globalId,\n fromGlobalId: args.fromGlobalId,\n toGlobalId: args.toGlobalId,\n edgeType,\n weight: args.weight,\n confidence: args.confidence,\n context: args.context,\n derivationType: args.derivationType,\n createdBy: args.createdBy,\n topicId: args.topicId,\n fromLayer: args.fromLayer,\n toLayer: args.toLayer,\n fromNodeType: args.fromNodeType,\n toNodeType: args.toNodeType,\n reasoningMethod: args.reasoningMethod,\n logicalRole: args.logicalRole,\n temporalClass: args.temporalClass,\n validFrom: args.validFrom,\n validUntil: args.validUntil,\n };\n}\n\nasync function mirrorEdgeToConvex(\n ctx: EdgeActionCtx,\n args: MirrorEdgeInput\n): Promise<void> {\n await ctx.runMutation(internal.epistemicEdges.mirrorEdgeToConvex, args);\n}\n\nasync function queueEdgeRetry(\n ctx: EdgeActionCtx,\n args: { globalId: string; operation: \"upsert\" | \"delete\"; error: string }\n): Promise<void> {\n await ctx.runMutation(internal.neo4jSyncHelpers.queueForRetry, {\n entityType: \"edge\",\n entityId: args.globalId,\n operation: args.operation,\n error: args.error,\n });\n}\n\nasync function mirrorCreatedEdgeIfNeeded(\n ctx: EdgeActionCtx,\n args: CreateEdgeInput,\n edgeType: string\n): Promise<void> {\n if (!needsDualWrite(edgeType)) {\n return;\n }\n try {\n await mirrorEdgeToConvex(ctx, mirrorInputFromCreateArgs(args, edgeType));\n } catch (error) {\n await queueEdgeRetry(ctx, {\n globalId: args.globalId,\n operation: \"upsert\",\n error: `Convex mirror failed: ${\n error instanceof Error ? error.message : \"Unknown error\"\n }`,\n });\n }\n}\n\nasync function handleMissingNeo4jEndpoints(\n ctx: EdgeActionCtx,\n args: CreateEdgeInput,\n edgeType: string\n) {\n await queueEdgeRetry(ctx, {\n globalId: args.globalId,\n operation: \"upsert\",\n error: `Source or target node not yet synced to Neo4j (from: ${args.fromGlobalId}, to: ${args.toGlobalId})`,\n });\n\n if (needsDualWrite(edgeType)) {\n try {\n await mirrorEdgeToConvex(ctx, mirrorInputFromCreateArgs(args, edgeType));\n } catch {\n // Retry was already queued for the Neo4j write; avoid hiding it.\n }\n }\n\n return {\n success: false,\n globalId: args.globalId,\n edgeType,\n queuedForRetry: true,\n reason: \"nodes_not_synced\",\n };\n}\n\nexport const createEdge = internalAction({\n args: {\n globalId: v.string(),\n fromGlobalId: v.string(),\n toGlobalId: v.string(),\n edgeType: v.string(),\n weight: v.optional(v.number()),\n confidence: v.optional(v.number()),\n context: v.optional(v.string()),\n derivationType: v.optional(v.string()),\n metadata: v.optional(v.any()),\n createdBy: v.string(),\n topicId: v.optional(v.string()),\n tenantId: v.optional(v.string()),\n workspaceId: v.optional(v.string()),\n fromLayer: v.optional(v.string()),\n toLayer: v.optional(v.string()),\n fromNodeType: v.optional(v.string()),\n toNodeType: v.optional(v.string()),\n reasoningMethod: v.optional(v.string()),\n logicalRole: v.optional(v.string()),\n temporalClass: v.optional(v.string()),\n validFrom: v.optional(v.number()),\n validUntil: v.optional(v.number()),\n },\n returns: permissiveReturn,\n handler: async (ctx, args) => {\n const connInfo = getConnectionInfo();\n if (!connInfo.configured) {\n throw new Error(\n \"[Neo4j Edge API] Neo4j not configured. Set NEO4J_URI, NEO4J_USER, NEO4J_PASSWORD\"\n );\n }\n\n const edgeType = normalizeEdgeType(args.edgeType);\n const relType = resolveRelationshipType(edgeType);\n const now = Date.now();\n const metadata = readMetadata(args.metadata);\n const properties = neo4jEdgeProperties(args, edgeType, metadata, now);\n\n const result = await runWriteTransaction<{ globalId: string }>(\n `\n MATCH (from {globalId: $fromGlobalId})\n MATCH (to {globalId: $toGlobalId})\n MERGE (from)-[r:${relType} {globalId: $globalId}]->(to)\n SET r += $properties\n RETURN r.globalId as globalId\n `,\n {\n fromGlobalId: args.fromGlobalId,\n toGlobalId: args.toGlobalId,\n globalId: args.globalId,\n properties,\n }\n );\n\n if (result.length === 0) {\n return handleMissingNeo4jEndpoints(ctx, args, edgeType);\n }\n\n await mirrorCreatedEdgeIfNeeded(ctx, args, edgeType);\n\n return {\n success: true,\n globalId: args.globalId,\n edgeType,\n dualWritten: needsDualWrite(edgeType),\n };\n },\n});\n\nexport const deleteEdge = internalAction({\n args: {\n globalId: v.string(),\n },\n returns: permissiveReturn,\n handler: async (ctx, args) => {\n const connInfo = getConnectionInfo();\n if (!connInfo.configured) {\n throw new Error(\"[Neo4j Edge API] Neo4j not configured\");\n }\n\n await runWriteTransaction(\n `\n MATCH ()-[r {globalId: $globalId}]->()\n DELETE r\n `,\n { globalId: args.globalId }\n );\n\n try {\n await ctx.runMutation(internal.epistemicEdges.deleteEdgeFromConvex, {\n globalId: args.globalId,\n });\n } catch {\n // The mirror may not exist for non-dual-write edge types.\n }\n\n return { success: true };\n },\n});\n\nexport const updateEdge = internalAction({\n args: {\n globalId: v.string(),\n weight: v.optional(v.number()),\n confidence: v.optional(v.number()),\n context: v.optional(v.string()),\n derivationType: v.optional(v.string()),\n },\n returns: permissiveReturn,\n handler: async (ctx, args) => {\n const connInfo = getConnectionInfo();\n if (!connInfo.configured) {\n throw new Error(\"[Neo4j Edge API] Neo4j not configured\");\n }\n\n const updates: Record<string, unknown> = { updatedAt: Date.now() };\n if (args.weight !== undefined) {\n updates.weight = args.weight;\n }\n if (args.confidence !== undefined) {\n updates.confidence = args.confidence;\n }\n if (args.context !== undefined) {\n updates.context = args.context;\n }\n if (args.derivationType !== undefined) {\n updates.derivationType = args.derivationType;\n }\n\n const result = await runWriteTransaction<{\n updated: boolean;\n edgeType: string;\n }>(\n `\n MATCH ()-[r {globalId: $globalId}]->()\n SET r += $updates\n RETURN true as updated, r.edgeType as edgeType\n `,\n { globalId: args.globalId, updates }\n );\n\n if (result.length === 0) {\n return { success: false, error: \"Edge not found\" };\n }\n\n const edgeType = result[0]?.edgeType;\n if (edgeType && needsDualWrite(edgeType)) {\n try {\n await ctx.runMutation(internal.epistemicEdges.updateEdgeInConvex, {\n globalId: args.globalId,\n weight: args.weight,\n confidence: args.confidence,\n context: args.context,\n derivationType: args.derivationType,\n });\n } catch {\n await queueEdgeRetry(ctx, {\n globalId: args.globalId,\n operation: \"upsert\",\n error: \"Convex mirror update failed\",\n });\n }\n }\n\n return { success: true, globalId: args.globalId };\n },\n});\n\nexport const getEdge = internalAction({\n args: {\n globalId: v.string(),\n },\n returns: permissiveReturn,\n handler: async (_ctx, args) => {\n const connInfo = getConnectionInfo();\n if (!connInfo.configured) {\n return null;\n }\n\n const result = await runCypher<{\n globalId: string;\n edgeType: string;\n fromGlobalId: string;\n toGlobalId: string;\n properties: Record<string, unknown>;\n }>(\n `\n MATCH (from)-[r {globalId: $globalId}]->(to)\n RETURN r.globalId as globalId,\n r.edgeType as edgeType,\n from.globalId as fromGlobalId,\n to.globalId as toGlobalId,\n properties(r) as properties\n LIMIT 1\n `,\n { globalId: args.globalId }\n );\n\n return result[0] ?? null;\n },\n});\n\nexport const retryProjectionByGlobalId = internalAction({\n args: {\n globalId: v.string(),\n },\n returns: permissiveReturn,\n handler: async (ctx, args) => {\n const connInfo = getConnectionInfo();\n if (!connInfo.configured) {\n return { success: false, error: \"[Neo4j Edge API] Neo4j not configured\" };\n }\n\n const result = await runCypher<{\n edgeType: string;\n fromGlobalId: string;\n toGlobalId: string;\n properties: Record<string, unknown>;\n }>(\n `\n MATCH (from)-[r {globalId: $globalId}]->(to)\n RETURN r.edgeType as edgeType,\n from.globalId as fromGlobalId,\n to.globalId as toGlobalId,\n properties(r) as properties\n LIMIT 1\n `,\n { globalId: args.globalId }\n );\n\n if (result.length === 0) {\n return {\n success: false,\n error: `[Neo4j Edge API] Edge not found in Neo4j: ${args.globalId}`,\n };\n }\n\n const [edge] = result;\n if (!edge) {\n return {\n success: false,\n error: `[Neo4j Edge API] Edge not found in Neo4j: ${args.globalId}`,\n };\n }\n if (!needsDualWrite(edge.edgeType)) {\n return {\n success: true,\n skipped: true,\n reason: \"edge_type_not_projected\",\n edgeType: edge.edgeType,\n };\n }\n\n const props = edge.properties || {};\n await mirrorEdgeToConvex(ctx, {\n globalId: args.globalId,\n fromGlobalId: edge.fromGlobalId,\n toGlobalId: edge.toGlobalId,\n edgeType: edge.edgeType,\n weight: readNumberProperty(props, \"weight\"),\n confidence: readNumberProperty(props, \"confidence\"),\n context: readStringProperty(props, \"context\"),\n derivationType: readStringProperty(props, \"derivationType\"),\n createdBy:\n readStringProperty(props, \"createdBy\") ?? \"neo4j_projection_retry\",\n topicId: readStringProperty(props, \"topicId\"),\n fromLayer: readStringProperty(props, \"fromLayer\"),\n toLayer: readStringProperty(props, \"toLayer\"),\n fromNodeType: readStringProperty(props, \"fromNodeType\"),\n toNodeType: readStringProperty(props, \"toNodeType\"),\n reasoningMethod: readStringProperty(props, \"reasoningMethod\"),\n logicalRole: readStringProperty(props, \"logicalRole\"),\n temporalClass: readStringProperty(props, \"temporalClass\"),\n validFrom: readNumberProperty(props, \"validFrom\"),\n validUntil: readNumberProperty(props, \"validUntil\"),\n });\n\n return { success: true, globalId: args.globalId, projected: true };\n },\n});\n"]}
1
+ {"version":3,"sources":["../src/convex.ts","../src/neo4jDriver.ts","../src/neo4jEdgeAPI.ts"],"names":["v"],"mappings":"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","file":"neo4jEdgeAPI.js","sourcesContent":["import { unsafeConvexAnyApi } from \"@lucern/contracts/convex/unsafeAnyApi\";\nimport {\n type ActionBuilder,\n actionGeneric,\n type GenericDataModel,\n type GenericDocument,\n internalActionGeneric,\n internalMutationGeneric,\n internalQueryGeneric,\n type MutationBuilder,\n type QueryBuilder,\n} from \"convex/server\";\nimport type { GenericId } from \"convex/values\";\n\nexport const internal = unsafeConvexAnyApi(\n \"graph-sync top-level module bundle lacks a committed Convex _generated/api surface\"\n);\n\ntype TableNames = string;\nexport type Id<TableName extends TableNames = string> = GenericId<TableName>;\ntype GraphSyncDocument<TableName extends string> = GenericDocument & {\n _creationTime: number;\n _id: GenericId<TableName>;\n};\n\ninterface GraphSyncTableInfo<\n Document extends GenericDocument,\n Indexes extends Record<string, string[]>,\n> {\n document: Document;\n fieldPaths: string;\n indexes: Indexes;\n searchIndexes: Record<string, never>;\n vectorIndexes: Record<string, never>;\n}\n\ntype EpistemicNodeDocument = GraphSyncDocument<\"epistemicNodes\"> & {\n globalId: string;\n nodeType: string;\n projectId?: string;\n updatedAt?: number;\n};\n\ntype EpistemicNodeEmbeddingDocument =\n GraphSyncDocument<\"epistemicNodeEmbeddings\"> & {\n embedding?: number[];\n nodeId: GenericId<\"epistemicNodes\">;\n };\n\ntype EpistemicEdgeDocument = GraphSyncDocument<\"epistemicEdges\"> & {\n edgeType: string;\n fromNodeId?: GenericId<\"epistemicNodes\"> | null;\n globalId?: string;\n sourceGlobalId?: string;\n targetGlobalId?: string;\n toNodeId?: GenericId<\"epistemicNodes\"> | null;\n};\n\ntype Neo4jSyncQueueDocument = GraphSyncDocument<\"neo4jSyncQueue\"> & {\n attempts?: number;\n createdAt?: number;\n entityId: string;\n entityType: \"node\" | \"edge\";\n lastAttemptAt?: number;\n lastError?: string;\n maxAttempts?: number;\n operation: \"upsert\" | \"delete\";\n status: \"pending\" | \"in_progress\" | \"failed\" | \"succeeded\";\n updatedAt?: number;\n};\n\ninterface GraphSyncDataModel extends GenericDataModel {\n epistemicEdges: GraphSyncTableInfo<\n EpistemicEdgeDocument,\n {\n by_globalId: [\"globalId\"];\n }\n >;\n epistemicNodeEmbeddings: GraphSyncTableInfo<\n EpistemicNodeEmbeddingDocument,\n {\n by_nodeId: [\"nodeId\"];\n }\n >;\n epistemicNodes: GraphSyncTableInfo<\n EpistemicNodeDocument,\n {\n by_nodeType: [\"nodeType\"];\n }\n >;\n neo4jSyncQueue: GraphSyncTableInfo<\n Neo4jSyncQueueDocument,\n {\n by_entity: [\"entityType\", \"entityId\"];\n by_status: [\"status\"];\n }\n >;\n}\n\nexport const action = actionGeneric as ActionBuilder<\n GraphSyncDataModel,\n \"public\"\n>;\nexport const internalAction = internalActionGeneric as ActionBuilder<\n GraphSyncDataModel,\n \"internal\"\n>;\nexport const internalMutation = internalMutationGeneric as MutationBuilder<\n GraphSyncDataModel,\n \"internal\"\n>;\nexport const internalQuery = internalQueryGeneric as QueryBuilder<\n GraphSyncDataModel,\n \"internal\"\n>;\n","// biome-ignore-all lint/style/useFilenamingConvention: Published @lucern/graph-sync/neo4jDriver subpath; rename needs an export-map migration.\n/**\n * neo4jDriver module implementation.\n */\n\n\"use node\";\n/**\n * Direct Neo4j Driver for Convex\n *\n * Uses the \"use node\" directive to enable Node.js runtime, allowing\n * direct use of the neo4j-driver package instead of HTTP proxies.\n *\n * Environment Variables (set per deployment via `npx convex env set`):\n * - NEO4J_URI: neo4j+s://xxx.databases.neo4j.io\n * - NEO4J_USER: neo4j\n * - NEO4J_PASSWORD: your-password\n *\n * @see /docs/architecture/UNIFIED_GRAPH_ARCHITECTURE.md\n */\n\nimport neo4j, { type Driver } from \"neo4j-driver\";\n\n// =============================================================================\n// VALID LABELS AND RELATIONSHIP TYPES (Security: Prevent Cypher Injection)\n// =============================================================================\n\nconst VALID_NODE_LABELS = new Set([\n // Ontological\n \"ValueChain\",\n \"Function\",\n \"FinSector\",\n \"Company\",\n \"Person\",\n \"Investor\",\n // Epistemic\n \"Theme\",\n \"Belief\",\n \"Question\",\n \"Evidence\",\n \"Source\",\n \"Decision\",\n \"Sprint\",\n \"Claim\",\n \"Synthesis\",\n \"Answer\",\n]);\n\nconst VALID_RELATIONSHIP_TYPES = new Set([\n // Cross-layer edges\n \"EXTRACTED_FROM\",\n \"ANSWERS\",\n \"RESPONDS_TO\",\n \"INFORMS\",\n \"QUALIFIES\",\n \"TESTS\",\n \"EXPLORES\",\n \"BASED_ON\",\n \"RELATES_TO_THESIS\",\n \"BELONGS_TO\",\n \"PLAYS_THEME\",\n // Same-layer edges\n \"SUPERSEDES\",\n \"SAME_AS\",\n \"DEPENDS_ON\",\n \"REINFORCES\",\n \"PARENT_OF\",\n \"CHILD_OF\",\n \"FALSIFIED_BY\",\n \"EXCLUSIVE_WITH\",\n \"COLLAPSES_IF\",\n \"CASCADE_FROM\",\n \"STRENGTHENED_BY\",\n \"WEAKENED_BY\",\n \"ALTERNATIVE_TO\",\n \"SUBSUMES\",\n \"VALIDATED_BY\",\n \"REQUIRED_FOR\",\n \"PREREQUISITE_FOR\",\n \"PARALLEL_TO\",\n \"CORROBORATES\",\n \"EXTENDS\",\n \"SAME_SOURCE_AS\",\n \"SAME_THEME_AS\",\n // Ontological\n \"EVALUATES\",\n \"PERSPECTIVE_ON\",\n \"WORKS_AT\",\n \"PARTICIPATES_IN\",\n \"PERFORMS\",\n \"FUNCTION_IN\",\n \"IMPACTS\",\n \"INVESTED_IN\",\n \"RAISED_FROM\",\n \"BASED_ON_BELIEF\",\n \"BASED_ON_QUESTION\",\n \"BLOCKED_BY_CONTRADICTION\",\n \"INFORMED_BY_THEME\",\n]);\n\nexport function validateLabel(label: string): void {\n if (!VALID_NODE_LABELS.has(label)) {\n throw new Error(\n `[Neo4j Security] Invalid node label: ${label}. Must be one of: ${Array.from(VALID_NODE_LABELS).join(\", \")}`\n );\n }\n}\n\nexport function validateRelType(relType: string): void {\n if (!VALID_RELATIONSHIP_TYPES.has(relType)) {\n throw new Error(\n `[Neo4j Security] Invalid relationship type: ${relType}. Must be one of: ${Array.from(VALID_RELATIONSHIP_TYPES).join(\", \")}`\n );\n }\n}\n\n// =============================================================================\n// DRIVER SINGLETON\n// =============================================================================\n\nlet driver: Driver | null = null;\n\nfunction getDriver(): Driver {\n if (!driver) {\n const uri = process.env.NEO4J_URI;\n const user = process.env.NEO4J_USER;\n const password = process.env.NEO4J_PASSWORD;\n\n if (!(uri && user && password)) {\n throw new Error(\n \"[Neo4j Driver] Missing credentials. Set NEO4J_URI, NEO4J_USER, NEO4J_PASSWORD via `npx convex env set`\"\n );\n }\n\n driver = neo4j.driver(uri, neo4j.auth.basic(user, password), {\n // Connection pool settings\n maxConnectionPoolSize: 50,\n connectionAcquisitionTimeout: 30_000,\n // Logging\n logging: {\n level: \"warn\",\n logger: (level, message) => console.log(`[Neo4j ${level}] ${message}`),\n },\n });\n }\n return driver;\n}\n\n// =============================================================================\n// QUERY CONFIGURATION\n// =============================================================================\n\n/**\n * Default query timeout in milliseconds.\n * Prevents expensive graph traversals from hanging indefinitely.\n */\nexport const DEFAULT_QUERY_TIMEOUT_MS = 30_000; // 30 seconds\n\n/**\n * Timeout for complex graph queries (cascade simulation, lineage traversal)\n */\nexport const COMPLEX_QUERY_TIMEOUT_MS = 60_000; // 60 seconds\n\n// =============================================================================\n// QUERY EXECUTION\n// =============================================================================\n\n/**\n * Convert JavaScript values to Neo4j-compatible types\n * Neo4j requires explicit integers, not floats\n */\nfunction toNeo4jParams(\n params: Record<string, unknown>\n): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(params)) {\n if (typeof value === \"number\" && Number.isInteger(value)) {\n // Convert JavaScript integers to Neo4j integers\n result[key] = neo4j.int(value);\n } else if (Array.isArray(value)) {\n result[key] = value.map((v) =>\n typeof v === \"number\" && Number.isInteger(v) ? neo4j.int(v) : v\n );\n } else {\n result[key] = value;\n }\n }\n return result;\n}\n\n/**\n * Execute a Cypher query and return results as typed objects\n *\n * @param query - Cypher query string\n * @param params - Query parameters\n * @param timeoutMs - Query timeout in milliseconds (default: 30s)\n */\nexport async function runCypher<T = Record<string, unknown>>(\n query: string,\n params: Record<string, unknown> = {},\n timeoutMs: number = DEFAULT_QUERY_TIMEOUT_MS\n): Promise<T[]> {\n const neo4jDriver = getDriver();\n const session = neo4jDriver.session();\n\n try {\n const neo4jParams = toNeo4jParams(params);\n const result = await session.run(query, neo4jParams, {\n timeout: neo4j.int(timeoutMs),\n });\n return result.records.map((record) => {\n const obj: Record<string, unknown> = {};\n for (const key of record.keys) {\n const field = String(key);\n obj[field] = convertNeo4jValue(record.get(field));\n }\n return obj as T;\n });\n } finally {\n await session.close();\n }\n}\n\n/**\n * Execute a write transaction (for mutations)\n *\n * @param query - Cypher query string\n * @param params - Query parameters\n * @param timeoutMs - Transaction timeout in milliseconds (default: 30s)\n */\nexport async function runWriteTransaction<T = Record<string, unknown>>(\n query: string,\n params: Record<string, unknown> = {},\n timeoutMs: number = DEFAULT_QUERY_TIMEOUT_MS\n): Promise<T[]> {\n const neo4jDriver = getDriver();\n const session = neo4jDriver.session();\n\n try {\n const neo4jParams = toNeo4jParams(params);\n const result = await session.executeWrite(\n async (tx) => await tx.run(query, neo4jParams),\n { timeout: timeoutMs }\n );\n return result.records.map((record) => {\n const obj: Record<string, unknown> = {};\n for (const key of record.keys) {\n const field = String(key);\n obj[field] = convertNeo4jValue(record.get(field));\n }\n return obj as T;\n });\n } finally {\n await session.close();\n }\n}\n\n/**\n * Execute multiple queries in a single transaction\n *\n * @param queries - Array of queries with parameters\n * @param timeoutMs - Transaction timeout in milliseconds (default: 60s for batch)\n */\nexport async function runBatchTransaction(\n queries: Array<{ query: string; params: Record<string, unknown> }>,\n timeoutMs: number = COMPLEX_QUERY_TIMEOUT_MS\n): Promise<void> {\n const neo4jDriver = getDriver();\n const session = neo4jDriver.session();\n\n try {\n await session.executeWrite(\n async (tx) => {\n for (const { query, params } of queries) {\n await tx.run(query, params);\n }\n },\n { timeout: timeoutMs }\n );\n } finally {\n await session.close();\n }\n}\n\n// =============================================================================\n// NODE OPERATIONS\n// =============================================================================\n\n/**\n * Upsert a node by globalId\n */\nexport async function upsertNode(\n label: string,\n globalId: string,\n properties: Record<string, unknown>\n): Promise<void> {\n validateLabel(label); // Security: prevent Cypher injection\n await runWriteTransaction(\n `\n MERGE (n:${label} {globalId: $globalId})\n SET n += $properties\n SET n.updatedAt = timestamp()\n `,\n { globalId, properties }\n );\n}\n\n/**\n * Delete a node by globalId\n */\nexport async function deleteNode(globalId: string): Promise<void> {\n await runWriteTransaction(\n `\n MATCH (n {globalId: $globalId})\n DETACH DELETE n\n `,\n { globalId }\n );\n}\n\n/**\n * Batch upsert nodes\n */\nexport async function batchUpsertNodes(\n label: string,\n nodes: Array<{ globalId: string; properties: Record<string, unknown> }>\n): Promise<void> {\n if (nodes.length === 0) {\n return;\n }\n\n validateLabel(label); // Security: prevent Cypher injection\n await runWriteTransaction(\n `\n UNWIND $nodes as node\n MERGE (n:${label} {globalId: node.globalId})\n SET n += node.properties\n SET n.updatedAt = timestamp()\n `,\n { nodes }\n );\n}\n\n// =============================================================================\n// EDGE OPERATIONS\n// =============================================================================\n\n/**\n * Upsert an edge by globalId\n */\nexport async function upsertEdge(\n relType: string,\n globalId: string,\n fromGlobalId: string,\n toGlobalId: string,\n properties: Record<string, unknown> = {}\n): Promise<void> {\n validateRelType(relType); // Security: prevent Cypher injection\n await runWriteTransaction(\n `\n MATCH (from {globalId: $fromGlobalId})\n MATCH (to {globalId: $toGlobalId})\n MERGE (from)-[r:${relType} {globalId: $globalId}]->(to)\n SET r += $properties\n SET r.updatedAt = timestamp()\n `,\n { globalId, fromGlobalId, toGlobalId, properties }\n );\n}\n\n/**\n * Delete an edge by globalId\n */\nexport async function deleteEdge(globalId: string): Promise<void> {\n await runWriteTransaction(\n `\n MATCH ()-[r {globalId: $globalId}]->()\n DELETE r\n `,\n { globalId }\n );\n}\n\n/**\n * Batch upsert edges\n */\nexport async function batchUpsertEdges(\n edges: Array<{\n relType: string;\n globalId: string;\n fromGlobalId: string;\n toGlobalId: string;\n properties?: Record<string, unknown>;\n }>\n): Promise<void> {\n if (edges.length === 0) {\n return;\n }\n\n // Group by relationship type for efficient batching\n const byType = new Map<string, typeof edges>();\n for (const edge of edges) {\n const existing = byType.get(edge.relType) || [];\n existing.push(edge);\n byType.set(edge.relType, existing);\n }\n\n const queries: Array<{ query: string; params: Record<string, unknown> }> = [];\n for (const [relType, typeEdges] of byType) {\n queries.push({\n query: `\n UNWIND $edges as edge\n MATCH (from {globalId: edge.fromGlobalId})\n MATCH (to {globalId: edge.toGlobalId})\n MERGE (from)-[r:${relType} {globalId: edge.globalId}]->(to)\n SET r += edge.properties\n SET r.updatedAt = timestamp()\n `,\n params: {\n edges: typeEdges.map((e) => ({\n globalId: e.globalId,\n fromGlobalId: e.fromGlobalId,\n toGlobalId: e.toGlobalId,\n properties: e.properties || {},\n })),\n },\n });\n }\n\n await runBatchTransaction(queries);\n}\n\n// =============================================================================\n// HEALTH CHECK\n// =============================================================================\n\n/**\n * Check if Neo4j connection is healthy\n */\nexport async function healthCheck(): Promise<{\n healthy: boolean;\n nodeCount?: number;\n error?: string;\n}> {\n try {\n const result = await runCypher<{ count: number }>(\n \"MATCH (n) RETURN count(n) as count LIMIT 1\"\n );\n return {\n healthy: true,\n nodeCount: result[0]?.count || 0,\n };\n } catch (error) {\n return {\n healthy: false,\n error: error instanceof Error ? error.message : \"Unknown error\",\n };\n }\n}\n\n/**\n * Get connection info (for debugging)\n */\nexport function getConnectionInfo(): {\n uri: string | undefined;\n user: string | undefined;\n configured: boolean;\n} {\n return {\n uri: process.env.NEO4J_URI,\n user: process.env.NEO4J_USER,\n configured: Boolean(\n process.env.NEO4J_URI &&\n process.env.NEO4J_USER &&\n process.env.NEO4J_PASSWORD\n ),\n };\n}\n\n// =============================================================================\n// VALUE CONVERSION\n// =============================================================================\n\n/**\n * Convert Neo4j types to plain JavaScript\n */\nfunction convertNeo4jValue(value: unknown): unknown {\n if (value === null || value === undefined) {\n return null;\n }\n\n // Handle Neo4j Integer\n if (neo4j.isInt(value)) {\n return neo4j.integer.toNumber(value);\n }\n\n // Handle Neo4j Date/Time types\n if (neo4j.isDate(value) || neo4j.isDateTime(value) || neo4j.isTime(value)) {\n return value.toString();\n }\n\n // Handle arrays\n if (Array.isArray(value)) {\n return value.map(convertNeo4jValue);\n }\n\n // Handle Node objects\n if (value && typeof value === \"object\" && \"properties\" in value) {\n const nodeObj = value as { properties: Record<string, unknown> };\n const result: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(nodeObj.properties)) {\n result[k] = convertNeo4jValue(v);\n }\n return result;\n }\n\n // Handle plain objects\n if (typeof value === \"object\") {\n const result: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(value as Record<string, unknown>)) {\n result[k] = convertNeo4jValue(v);\n }\n return result;\n }\n\n return value;\n}\n\n// =============================================================================\n// CLEANUP\n// =============================================================================\n\n/**\n * Close the driver connection (for graceful shutdown)\n */\nexport async function closeDriver(): Promise<void> {\n if (driver) {\n await driver.close();\n driver = null;\n }\n}\n","// biome-ignore-all lint/style/useFilenamingConvention: Published @lucern/graph-sync/neo4jEdgeAPI subpath; rename needs an export-map migration.\n\"use node\";\n\n/**\n * Neo4j edge API host actions.\n *\n * The reasoning kernel schedules these actions through the tenant Convex host\n * when optional graph mirroring is installed. Neo4j remains authoritative for\n * traversal topology; Convex mirrors selected edge types for realtime reads.\n */\n\nimport { permissiveReturn } from \"@lucern/contracts/schema-helpers/validators\";\nimport { getNeo4jRelType } from \"@lucern/graph-primitives/graphTypes\";\nimport { v } from \"convex/values\";\nimport { internal, internalAction } from \"./convex\";\nimport {\n getConnectionInfo,\n runCypher,\n runWriteTransaction,\n} from \"./neo4jDriver\";\n\nexport const DUAL_WRITE_EDGE_TYPES = [\n \"supports\",\n \"informs\",\n \"tests\",\n \"depends_on\",\n \"derived_from\",\n \"contains\",\n \"supersedes\",\n \"extracted_from\",\n \"responds_to\",\n \"based_on\",\n \"answers\",\n \"belongs_to\",\n \"relates_to_thesis\",\n \"corroborates\",\n \"extends\",\n \"same_source_as\",\n \"same_theme_as\",\n \"plays_theme\",\n \"impacts\",\n \"evaluates\",\n \"mentioned_in\",\n \"perspective_on\",\n] as const;\n\nexport type DualWriteEdgeType = (typeof DUAL_WRITE_EDGE_TYPES)[number];\nconst LOWER_EDGE_TYPE_REGEX = /^[a-z0-9_]+$/u;\nconst UPPER_EDGE_TYPE_REGEX = /^[A-Z0-9_]+$/u;\n\ninterface EdgeActionCtx {\n runMutation<Result = unknown>(\n functionReference: unknown,\n args?: unknown\n ): Promise<Result>;\n}\n\ninterface CreateEdgeInput {\n confidence?: number;\n context?: string;\n createdBy: string;\n derivationType?: string;\n edgeType: string;\n fromGlobalId: string;\n fromLayer?: string;\n fromNodeType?: string;\n globalId: string;\n logicalRole?: string;\n metadata?: unknown;\n reasoningMethod?: string;\n temporalClass?: string;\n tenantId?: string;\n toGlobalId: string;\n toLayer?: string;\n toNodeType?: string;\n topicId?: string;\n validFrom?: number;\n validUntil?: number;\n weight?: number;\n workspaceId?: string;\n}\n\ninterface MirrorEdgeInput {\n confidence?: number;\n context?: string;\n createdBy: string;\n derivationType?: string;\n edgeType: string;\n fromGlobalId: string;\n fromLayer?: string;\n fromNodeType?: string;\n globalId: string;\n logicalRole?: string;\n reasoningMethod?: string;\n temporalClass?: string;\n toGlobalId: string;\n toLayer?: string;\n toNodeType?: string;\n topicId?: string;\n validFrom?: number;\n validUntil?: number;\n weight?: number;\n}\n\nexport function needsDualWrite(edgeType: string): boolean {\n return DUAL_WRITE_EDGE_TYPES.includes(edgeType as DualWriteEdgeType);\n}\n\nfunction normalizeEdgeType(edgeType: string): string {\n const normalized = edgeType.trim().toLowerCase();\n if (!LOWER_EDGE_TYPE_REGEX.test(normalized)) {\n throw new Error(`[Neo4j Edge API] Invalid edge type: ${edgeType}`);\n }\n return normalized;\n}\n\nfunction resolveRelationshipType(edgeType: string): string {\n const relType = getNeo4jRelType(edgeType);\n if (!UPPER_EDGE_TYPE_REGEX.test(relType)) {\n throw new Error(`[Neo4j Edge API] Invalid relationship type: ${relType}`);\n }\n return relType;\n}\n\nfunction readStringProperty(\n source: Record<string, unknown> | undefined,\n key: string\n): string | undefined {\n const value = source?.[key];\n return typeof value === \"string\" && value.trim().length > 0\n ? value.trim()\n : undefined;\n}\n\nfunction readNumberProperty(\n source: Record<string, unknown> | undefined,\n key: string\n): number | undefined {\n const value = source?.[key];\n return typeof value === \"number\" && Number.isFinite(value)\n ? value\n : undefined;\n}\n\nfunction metadataSummary(\n metadata: Record<string, unknown> | undefined\n): string | undefined {\n if (!metadata) {\n return;\n }\n\n return Object.entries(metadata)\n .map(([key, value]) => `${key}=${String(value)}`)\n .slice(0, 8)\n .join(\" | \");\n}\n\nfunction readMetadata(metadata: unknown): Record<string, unknown> | undefined {\n return metadata && typeof metadata === \"object\" && !Array.isArray(metadata)\n ? (metadata as Record<string, unknown>)\n : undefined;\n}\n\nfunction neo4jEdgeProperties(\n args: CreateEdgeInput,\n edgeType: string,\n metadata: Record<string, unknown> | undefined,\n now: number\n): Record<string, unknown> {\n return {\n globalId: args.globalId,\n edgeType,\n weight: args.weight ?? 1,\n confidence:\n args.confidence ?? readNumberProperty(metadata, \"confidence\") ?? 1,\n context: args.context ?? metadataSummary(metadata) ?? \"\",\n derivationType: args.derivationType ?? \"\",\n createdBy: args.createdBy,\n createdAt: now,\n updatedAt: now,\n topicId: args.topicId ?? readStringProperty(metadata, \"topicId\") ?? \"\",\n tenantId: args.tenantId ?? readStringProperty(metadata, \"tenantId\") ?? \"\",\n workspaceId:\n args.workspaceId ?? readStringProperty(metadata, \"workspaceId\") ?? \"\",\n fromLayer: args.fromLayer ?? \"\",\n toLayer: args.toLayer ?? \"\",\n fromNodeType: args.fromNodeType ?? \"\",\n toNodeType: args.toNodeType ?? \"\",\n reasoningMethod: args.reasoningMethod ?? \"\",\n logicalRole: args.logicalRole ?? \"\",\n temporalClass: args.temporalClass ?? \"structural\",\n validFrom: args.validFrom ?? now,\n validUntil: args.validUntil ?? null,\n };\n}\n\nfunction mirrorInputFromCreateArgs(\n args: CreateEdgeInput,\n edgeType: string\n): MirrorEdgeInput {\n return {\n globalId: args.globalId,\n fromGlobalId: args.fromGlobalId,\n toGlobalId: args.toGlobalId,\n edgeType,\n weight: args.weight,\n confidence: args.confidence,\n context: args.context,\n derivationType: args.derivationType,\n createdBy: args.createdBy,\n topicId: args.topicId,\n fromLayer: args.fromLayer,\n toLayer: args.toLayer,\n fromNodeType: args.fromNodeType,\n toNodeType: args.toNodeType,\n reasoningMethod: args.reasoningMethod,\n logicalRole: args.logicalRole,\n temporalClass: args.temporalClass,\n validFrom: args.validFrom,\n validUntil: args.validUntil,\n };\n}\n\nasync function mirrorEdgeToConvex(\n ctx: EdgeActionCtx,\n args: MirrorEdgeInput\n): Promise<void> {\n await ctx.runMutation(internal.epistemicEdges.mirrorEdgeToConvex, args);\n}\n\nasync function queueEdgeRetry(\n ctx: EdgeActionCtx,\n args: { globalId: string; operation: \"upsert\" | \"delete\"; error: string }\n): Promise<void> {\n await ctx.runMutation(internal.neo4jSyncHelpers.queueForRetry, {\n entityType: \"edge\",\n entityId: args.globalId,\n operation: args.operation,\n error: args.error,\n });\n}\n\nasync function mirrorCreatedEdgeIfNeeded(\n ctx: EdgeActionCtx,\n args: CreateEdgeInput,\n edgeType: string\n): Promise<void> {\n if (!needsDualWrite(edgeType)) {\n return;\n }\n try {\n await mirrorEdgeToConvex(ctx, mirrorInputFromCreateArgs(args, edgeType));\n } catch (error) {\n await queueEdgeRetry(ctx, {\n globalId: args.globalId,\n operation: \"upsert\",\n error: `Convex mirror failed: ${\n error instanceof Error ? error.message : \"Unknown error\"\n }`,\n });\n }\n}\n\nasync function handleMissingNeo4jEndpoints(\n ctx: EdgeActionCtx,\n args: CreateEdgeInput,\n edgeType: string\n) {\n await queueEdgeRetry(ctx, {\n globalId: args.globalId,\n operation: \"upsert\",\n error: `Source or target node not yet synced to Neo4j (from: ${args.fromGlobalId}, to: ${args.toGlobalId})`,\n });\n\n if (needsDualWrite(edgeType)) {\n try {\n await mirrorEdgeToConvex(ctx, mirrorInputFromCreateArgs(args, edgeType));\n } catch {\n // Retry was already queued for the Neo4j write; avoid hiding it.\n }\n }\n\n return {\n success: false,\n globalId: args.globalId,\n edgeType,\n queuedForRetry: true,\n reason: \"nodes_not_synced\",\n };\n}\n\nexport const createEdge = internalAction({\n args: {\n globalId: v.string(),\n fromGlobalId: v.string(),\n toGlobalId: v.string(),\n edgeType: v.string(),\n weight: v.optional(v.number()),\n confidence: v.optional(v.number()),\n context: v.optional(v.string()),\n derivationType: v.optional(v.string()),\n metadata: v.optional(v.any()),\n createdBy: v.string(),\n topicId: v.optional(v.string()),\n tenantId: v.optional(v.string()),\n workspaceId: v.optional(v.string()),\n fromLayer: v.optional(v.string()),\n toLayer: v.optional(v.string()),\n fromNodeType: v.optional(v.string()),\n toNodeType: v.optional(v.string()),\n reasoningMethod: v.optional(v.string()),\n logicalRole: v.optional(v.string()),\n temporalClass: v.optional(v.string()),\n validFrom: v.optional(v.number()),\n validUntil: v.optional(v.number()),\n },\n returns: permissiveReturn,\n handler: async (ctx, args) => {\n const connInfo = getConnectionInfo();\n if (!connInfo.configured) {\n throw new Error(\n \"[Neo4j Edge API] Neo4j not configured. Set NEO4J_URI, NEO4J_USER, NEO4J_PASSWORD\"\n );\n }\n\n const edgeType = normalizeEdgeType(args.edgeType);\n const relType = resolveRelationshipType(edgeType);\n const now = Date.now();\n const metadata = readMetadata(args.metadata);\n const properties = neo4jEdgeProperties(args, edgeType, metadata, now);\n\n const result = await runWriteTransaction<{ globalId: string }>(\n `\n MATCH (from {globalId: $fromGlobalId})\n MATCH (to {globalId: $toGlobalId})\n MERGE (from)-[r:${relType} {globalId: $globalId}]->(to)\n SET r += $properties\n RETURN r.globalId as globalId\n `,\n {\n fromGlobalId: args.fromGlobalId,\n toGlobalId: args.toGlobalId,\n globalId: args.globalId,\n properties,\n }\n );\n\n if (result.length === 0) {\n return handleMissingNeo4jEndpoints(ctx, args, edgeType);\n }\n\n await mirrorCreatedEdgeIfNeeded(ctx, args, edgeType);\n\n return {\n success: true,\n globalId: args.globalId,\n edgeType,\n dualWritten: needsDualWrite(edgeType),\n };\n },\n});\n\nexport const deleteEdge = internalAction({\n args: {\n globalId: v.string(),\n },\n returns: permissiveReturn,\n handler: async (ctx, args) => {\n const connInfo = getConnectionInfo();\n if (!connInfo.configured) {\n throw new Error(\"[Neo4j Edge API] Neo4j not configured\");\n }\n\n await runWriteTransaction(\n `\n MATCH ()-[r {globalId: $globalId}]->()\n DELETE r\n `,\n { globalId: args.globalId }\n );\n\n try {\n await ctx.runMutation(internal.epistemicEdges.deleteEdgeFromConvex, {\n globalId: args.globalId,\n });\n } catch {\n // The mirror may not exist for non-dual-write edge types.\n }\n\n return { success: true };\n },\n});\n\nexport const updateEdge = internalAction({\n args: {\n globalId: v.string(),\n weight: v.optional(v.number()),\n confidence: v.optional(v.number()),\n context: v.optional(v.string()),\n derivationType: v.optional(v.string()),\n },\n returns: permissiveReturn,\n handler: async (ctx, args) => {\n const connInfo = getConnectionInfo();\n if (!connInfo.configured) {\n throw new Error(\"[Neo4j Edge API] Neo4j not configured\");\n }\n\n const updates: Record<string, unknown> = { updatedAt: Date.now() };\n if (args.weight !== undefined) {\n updates.weight = args.weight;\n }\n if (args.confidence !== undefined) {\n updates.confidence = args.confidence;\n }\n if (args.context !== undefined) {\n updates.context = args.context;\n }\n if (args.derivationType !== undefined) {\n updates.derivationType = args.derivationType;\n }\n\n const result = await runWriteTransaction<{\n updated: boolean;\n edgeType: string;\n }>(\n `\n MATCH ()-[r {globalId: $globalId}]->()\n SET r += $updates\n RETURN true as updated, r.edgeType as edgeType\n `,\n { globalId: args.globalId, updates }\n );\n\n if (result.length === 0) {\n return { success: false, error: \"Edge not found\" };\n }\n\n const edgeType = result[0]?.edgeType;\n if (edgeType && needsDualWrite(edgeType)) {\n try {\n await ctx.runMutation(internal.epistemicEdges.updateEdgeInConvex, {\n globalId: args.globalId,\n weight: args.weight,\n confidence: args.confidence,\n context: args.context,\n derivationType: args.derivationType,\n });\n } catch {\n await queueEdgeRetry(ctx, {\n globalId: args.globalId,\n operation: \"upsert\",\n error: \"Convex mirror update failed\",\n });\n }\n }\n\n return { success: true, globalId: args.globalId };\n },\n});\n\nexport const getEdge = internalAction({\n args: {\n globalId: v.string(),\n },\n returns: permissiveReturn,\n handler: async (_ctx, args) => {\n const connInfo = getConnectionInfo();\n if (!connInfo.configured) {\n return null;\n }\n\n const result = await runCypher<{\n globalId: string;\n edgeType: string;\n fromGlobalId: string;\n toGlobalId: string;\n properties: Record<string, unknown>;\n }>(\n `\n MATCH (from)-[r {globalId: $globalId}]->(to)\n RETURN r.globalId as globalId,\n r.edgeType as edgeType,\n from.globalId as fromGlobalId,\n to.globalId as toGlobalId,\n properties(r) as properties\n LIMIT 1\n `,\n { globalId: args.globalId }\n );\n\n return result[0] ?? null;\n },\n});\n\nexport const retryProjectionByGlobalId = internalAction({\n args: {\n globalId: v.string(),\n },\n returns: permissiveReturn,\n handler: async (ctx, args) => {\n const connInfo = getConnectionInfo();\n if (!connInfo.configured) {\n return { success: false, error: \"[Neo4j Edge API] Neo4j not configured\" };\n }\n\n const result = await runCypher<{\n edgeType: string;\n fromGlobalId: string;\n toGlobalId: string;\n properties: Record<string, unknown>;\n }>(\n `\n MATCH (from)-[r {globalId: $globalId}]->(to)\n RETURN r.edgeType as edgeType,\n from.globalId as fromGlobalId,\n to.globalId as toGlobalId,\n properties(r) as properties\n LIMIT 1\n `,\n { globalId: args.globalId }\n );\n\n if (result.length === 0) {\n return {\n success: false,\n error: `[Neo4j Edge API] Edge not found in Neo4j: ${args.globalId}`,\n };\n }\n\n const [edge] = result;\n if (!edge) {\n return {\n success: false,\n error: `[Neo4j Edge API] Edge not found in Neo4j: ${args.globalId}`,\n };\n }\n if (!needsDualWrite(edge.edgeType)) {\n return {\n success: true,\n skipped: true,\n reason: \"edge_type_not_projected\",\n edgeType: edge.edgeType,\n };\n }\n\n const props = edge.properties || {};\n await mirrorEdgeToConvex(ctx, {\n globalId: args.globalId,\n fromGlobalId: edge.fromGlobalId,\n toGlobalId: edge.toGlobalId,\n edgeType: edge.edgeType,\n weight: readNumberProperty(props, \"weight\"),\n confidence: readNumberProperty(props, \"confidence\"),\n context: readStringProperty(props, \"context\"),\n derivationType: readStringProperty(props, \"derivationType\"),\n createdBy:\n readStringProperty(props, \"createdBy\") ?? \"neo4j_projection_retry\",\n topicId: readStringProperty(props, \"topicId\"),\n fromLayer: readStringProperty(props, \"fromLayer\"),\n toLayer: readStringProperty(props, \"toLayer\"),\n fromNodeType: readStringProperty(props, \"fromNodeType\"),\n toNodeType: readStringProperty(props, \"toNodeType\"),\n reasoningMethod: readStringProperty(props, \"reasoningMethod\"),\n logicalRole: readStringProperty(props, \"logicalRole\"),\n temporalClass: readStringProperty(props, \"temporalClass\"),\n validFrom: readNumberProperty(props, \"validFrom\"),\n validUntil: readNumberProperty(props, \"validUntil\"),\n });\n\n return { success: true, globalId: args.globalId, projected: true };\n },\n});\n"]}