@anvia/neo4j 1.0.8 → 1.0.10

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.
@@ -2,11 +2,15 @@ import {
2
2
  ManagedNeo4jKnowledgeGraph,
3
3
  Neo4jKnowledgeGraphBase,
4
4
  finiteScore,
5
+ managedPathPredicate,
6
+ managedScopeParameters,
7
+ managedScopePredicate,
5
8
  positiveInteger,
6
9
  quoteIdentifier,
7
10
  strictProperties,
11
+ tenantScopePredicate,
8
12
  throwIfAborted
9
- } from "./chunk-QNHOT7P2.js";
13
+ } from "./chunk-EUZ5C6OC.js";
10
14
 
11
15
  // src/retrieve.ts
12
16
  import { embedText } from "@anvia/core/embeddings";
@@ -92,12 +96,19 @@ async function retrieveGraphContext(options) {
92
96
  }
93
97
  async function vectorSearch(graph, labels, indexName, vector, limit, entryRelationshipType, abortSignal) {
94
98
  const labelExpression = labels.map(quoteIdentifier).join("|");
99
+ const vectorFilter = graph instanceof ManagedNeo4jKnowledgeGraph && graph.namespace !== void 0 ? ` WHERE seed.${quoteIdentifier("__anvia_namespace")} = $namespace` : "";
100
+ const postFilter = managedSearchPredicate(
101
+ graph,
102
+ "seed",
103
+ entryRelationshipType === "ANVIA_MENTIONS"
104
+ );
95
105
  const result = await graph.query(
96
106
  `CYPHER 25
97
107
  MATCH (seed:${labelExpression})
98
- SEARCH seed IN (VECTOR INDEX ${quoteIdentifier(indexName)} FOR $vector LIMIT $limit) SCORE AS score
108
+ SEARCH seed IN (VECTOR INDEX ${quoteIdentifier(indexName)} FOR $vector${vectorFilter} LIMIT $limit) SCORE AS score
109
+ ${postFilter}
99
110
  RETURN elementId(seed) AS elementId, labels(seed) AS labels, properties(seed) AS properties, score`,
100
- { vector, limit: int(limit) },
111
+ managedQueryParameters(graph, { vector, limit: int(limit) }),
101
112
  abortSignal
102
113
  );
103
114
  return result.records.map((record) => ({ ...parseSearchHit(record), entryRelationshipType }));
@@ -105,8 +116,13 @@ RETURN elementId(seed) AS elementId, labels(seed) AS labels, properties(seed) AS
105
116
  async function fulltextSearch(graph, indexName, query, limit, entryRelationshipType, abortSignal) {
106
117
  const result = await graph.query(
107
118
  `CALL db.index.fulltext.queryNodes($indexName, $query, {limit: $limit}) YIELD node AS seed, score
119
+ ${managedSearchPredicate(graph, "seed", entryRelationshipType === "ANVIA_MENTIONS")}
108
120
  RETURN elementId(seed) AS elementId, labels(seed) AS labels, properties(seed) AS properties, score`,
109
- { indexName, query: escapeLucene(query), limit: int(limit) },
121
+ managedQueryParameters(graph, {
122
+ indexName,
123
+ query: scopedFulltextQuery(graph, query),
124
+ limit: int(limit)
125
+ }),
110
126
  abortSignal
111
127
  );
112
128
  return result.records.map((record) => ({ ...parseSearchHit(record), entryRelationshipType }));
@@ -158,12 +174,13 @@ async function hydrateEvidence(graph, context, options, abortSignal) {
158
174
  const result = await graph.query(
159
175
  `MATCH (d:${quoteIdentifier(graph.resources.labels.document)})-[:${quoteIdentifier("ANVIA_HAS_CHUNK")}]->(c:${quoteIdentifier(graph.resources.labels.chunk)})
160
176
  WHERE c.${quoteIdentifier("__anvia_id")} IN $chunkIds
177
+ ${tenantNodeAndPredicate(graph, "d")}${tenantNodeAndPredicate(graph, "c")}
161
178
  RETURN c.${quoteIdentifier("__anvia_id")} AS chunkId,
162
179
  d.${quoteIdentifier("__anvia_id")} AS documentId,
163
180
  c.${quoteIdentifier("__anvia_index")} AS index,
164
181
  c.${quoteIdentifier("__anvia_text")} AS text,
165
182
  properties(c) AS properties`,
166
- { chunkIds },
183
+ managedQueryParameters(graph, { chunkIds }),
167
184
  abortSignal
168
185
  );
169
186
  const byId = /* @__PURE__ */ new Map();
@@ -228,9 +245,11 @@ async function traverse(graph, seeds, options, abortSignal) {
228
245
  for (const [relationshipType, group] of entryGroups) {
229
246
  const entries = await graph.query(
230
247
  `MATCH (seed) WHERE elementId(seed) IN $seedIds
231
- MATCH (seed)-[:${quoteIdentifier(relationshipType)}]->(entry)
248
+ ${tenantNodePredicate(graph, "seed", "AND")}
249
+ MATCH (seed)-[entryRelationship:${quoteIdentifier(relationshipType)}]->(entry)
250
+ WHERE true${managedNodeAndPredicate(graph, "entry")}${tenantNodeAndPredicate(graph, "entryRelationship")}
232
251
  RETURN DISTINCT elementId(entry) AS elementId`,
233
- { seedIds: group.map((seed) => seed.elementId) },
252
+ managedQueryParameters(graph, { seedIds: group.map((seed) => seed.elementId) }),
234
253
  abortSignal
235
254
  );
236
255
  for (const record of entries.records) {
@@ -243,22 +262,24 @@ RETURN DISTINCT elementId(entry) AS elementId`,
243
262
  const pathLimit = Math.max(options.maxNodes, options.maxRelationships);
244
263
  const seedNodes = await graph.query(
245
264
  `MATCH (node) WHERE elementId(node) IN $seedIds
265
+ ${managedNodePredicate(graph, "node", "AND")}
246
266
  RETURN {elementId: elementId(node), labels: labels(node), properties: properties(node)} AS node`,
247
- { seedIds: limitedSeedIds },
267
+ managedQueryParameters(graph, { seedIds: limitedSeedIds }),
248
268
  abortSignal
249
269
  );
250
270
  const result = await graph.query(
251
271
  `MATCH (seed) WHERE elementId(seed) IN $seedIds
272
+ ${managedNodePredicate(graph, "seed", "AND")}
252
273
  MATCH path = ${pattern}
253
- WHERE all(rel IN relationships(path) WHERE type(rel) IN $relationshipTypes)
274
+ WHERE all(rel IN relationships(path) WHERE type(rel) IN $relationshipTypes${managedRelationshipAndPredicate(graph, "rel")})${managedPathAndPredicate(graph)}
254
275
  RETURN [item IN nodes(path) | {elementId: elementId(item), labels: labels(item), properties: properties(item)}] AS nodes,
255
276
  [item IN relationships(path) | {elementId: elementId(item), type: type(item), properties: properties(item), from: elementId(startNode(item)), to: elementId(endNode(item))}] AS relationships
256
277
  LIMIT $pathLimit`,
257
- {
278
+ managedQueryParameters(graph, {
258
279
  seedIds: limitedSeedIds,
259
280
  relationshipTypes: options.relationships,
260
281
  pathLimit: int(pathLimit)
261
- },
282
+ }),
262
283
  abortSignal
263
284
  );
264
285
  const nodes = /* @__PURE__ */ new Map();
@@ -308,6 +329,35 @@ function traversalPattern(direction, maxDepth) {
308
329
  }
309
330
  return `(seed)-[*1..${maxDepth}]-(node)`;
310
331
  }
332
+ function managedQueryParameters(graph, parameters) {
333
+ return managedScopeParameters(managedScope(graph), parameters);
334
+ }
335
+ function managedNodePredicate(graph, variable, prefix) {
336
+ return managedScopePredicate(managedScope(graph), variable, prefix);
337
+ }
338
+ function managedSearchPredicate(graph, variable, chunkSeed) {
339
+ return chunkSeed && graph.namespace === void 0 ? "" : managedNodePredicate(graph, variable, "WHERE");
340
+ }
341
+ function managedNodeAndPredicate(graph, variable) {
342
+ return managedScopePredicate(managedScope(graph), variable, " AND");
343
+ }
344
+ function managedRelationshipAndPredicate(graph, variable) {
345
+ return managedNodeAndPredicate(graph, variable);
346
+ }
347
+ function tenantNodePredicate(graph, variable, prefix) {
348
+ const scope = managedScope(graph);
349
+ return scope === void 0 ? "" : tenantScopePredicate(scope, variable, prefix);
350
+ }
351
+ function tenantNodeAndPredicate(graph, variable) {
352
+ const predicate = tenantNodePredicate(graph, variable, "AND");
353
+ return predicate.length === 0 ? "" : ` ${predicate}`;
354
+ }
355
+ function managedPathAndPredicate(graph) {
356
+ return managedPathPredicate(managedScope(graph), false);
357
+ }
358
+ function managedScope(graph) {
359
+ return graph instanceof ManagedNeo4jKnowledgeGraph ? { graph: graph.name, namespace: graph.namespace } : void 0;
360
+ }
311
361
  function contextNode(value, schema) {
312
362
  const labels = value.labels;
313
363
  const raw = value.properties;
@@ -456,6 +506,10 @@ function escapeLucene(value) {
456
506
  }
457
507
  return escaped;
458
508
  }
509
+ function scopedFulltextQuery(graph, value) {
510
+ const query = escapeLucene(value);
511
+ return graph instanceof ManagedNeo4jKnowledgeGraph && graph.namespace !== void 0 ? `(${query}) AND __anvia_namespace:${escapeLucene(graph.namespace)}` : query;
512
+ }
459
513
  function groupBy(values, keyFor) {
460
514
  const groups = /* @__PURE__ */ new Map();
461
515
  for (const value of values) {
@@ -470,4 +524,4 @@ function groupBy(values, keyFor) {
470
524
  export {
471
525
  retrieveGraphContext
472
526
  };
473
- //# sourceMappingURL=chunk-YLW4LCKJ.js.map
527
+ //# sourceMappingURL=chunk-YCJZAWLH.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/retrieve.ts"],"sourcesContent":["import { embedText } from \"@anvia/core/embeddings\";\nimport { int, isInt, type Record as Neo4jRecord } from \"neo4j-driver\";\nimport { ManagedNeo4jKnowledgeGraph, Neo4jKnowledgeGraphBase } from \"./graph.js\";\nimport {\n finiteScore,\n positiveInteger,\n quoteIdentifier,\n strictProperties,\n throwIfAborted,\n} from \"./helpers.js\";\nimport {\n managedPathPredicate,\n managedScopeParameters,\n managedScopePredicate,\n tenantScopePredicate,\n type Neo4jManagedScope,\n} from \"./managed-scope.js\";\nimport type {\n Neo4jGraphContext,\n Neo4jGraphContextNode,\n Neo4jGraphContextRelationship,\n Neo4jGraphContextSeed,\n Neo4jGraphEvidence,\n Neo4jGraphEvidenceOptions,\n Neo4jGraphSchema,\n RetrieveGraphContextOptions,\n} from \"./types.js\";\n\ntype SearchHit = {\n elementId: string;\n labels: string[];\n properties: Record<string, unknown>;\n score: number;\n entryRelationshipType?: string | undefined;\n};\n\nexport async function retrieveGraphContext<Schema extends Neo4jGraphSchema>(\n options: RetrieveGraphContextOptions<Schema>,\n): Promise<Neo4jGraphContext> {\n if (!(options.graph instanceof Neo4jKnowledgeGraphBase)) {\n throw new TypeError(\"retrieveGraphContext requires a Neo4j knowledge graph registration.\");\n }\n if (typeof options.query !== \"string\" || options.query.trim().length === 0) {\n throw new TypeError(\"Graph retrieval query must be a non-empty string.\");\n }\n validateSearch(options.search);\n validateTraversal(options.graph.schema, options.traversal);\n validateEvidence(options.graph.evidenceCapability, options.evidence);\n throwIfAborted(options.abortSignal);\n const graph = options.graph as Neo4jKnowledgeGraphBase<Schema>;\n const selectedSeeds = options.search.seeds.map((name) => ({ name, seed: graph.seed(name) }));\n const expectedDimensions = selectedSeeds[0]?.seed.vectorIndex.dimensions;\n if (\n expectedDimensions === undefined ||\n selectedSeeds.some((item) => item.seed.vectorIndex.dimensions !== expectedDimensions)\n ) {\n throw new TypeError(\"Selected Neo4j graph seeds must use the same vector dimensions.\");\n }\n if (options.model.dimensions !== undefined && options.model.dimensions !== expectedDimensions) {\n throw new TypeError(\n `Embedding model dimensions ${options.model.dimensions} do not match Neo4j graph dimensions ${expectedDimensions}.`,\n );\n }\n if (options.search.type === \"hybrid\") {\n for (const { name, seed } of selectedSeeds) {\n if (seed.fulltextIndex === undefined) {\n throw new TypeError(`Neo4j graph seed ${name} does not declare a full-text index.`);\n }\n }\n }\n const { embedding } = await embedText({\n model: options.model,\n text: options.query,\n retries: options.retries,\n abortSignal: options.abortSignal,\n });\n if (embedding.vector.length !== expectedDimensions) {\n throw new TypeError(\n `Query embedding dimensions ${embedding.vector.length} do not match Neo4j graph dimensions ${expectedDimensions}.`,\n );\n }\n\n const resultLists: SearchHit[][] = [];\n for (const { seed } of selectedSeeds) {\n const limit =\n options.search.type === \"hybrid\" ? options.search.candidatesPerSeed : options.search.topK;\n resultLists.push(\n await vectorSearch(\n graph,\n seed.labels,\n seed.vectorIndex.name,\n embedding.vector,\n limit,\n seed.entryRelationshipType,\n options.abortSignal,\n ),\n );\n if (options.search.type === \"hybrid\") {\n const fulltextIndex = seed.fulltextIndex;\n if (fulltextIndex === undefined) {\n throw new TypeError(\"Hybrid Neo4j graph retrieval requires a full-text index.\");\n }\n resultLists.push(\n await fulltextSearch(\n graph,\n fulltextIndex.name,\n options.query,\n limit,\n seed.entryRelationshipType,\n options.abortSignal,\n ),\n );\n }\n }\n\n const hits =\n options.search.type === \"hybrid\"\n ? fuseResults(resultLists, options.search.topK, options.search.rrfK)\n : vectorResults(resultLists[0] ?? [], options.search.topK, options.search.minScore);\n throwIfAborted(options.abortSignal);\n const seeds = hits.map((hit) => seedFromHit(hit, options.graph.schema));\n const traversed =\n hits.length === 0\n ? { nodes: [], relationships: [] }\n : await traverse(graph, hits, options.traversal, options.abortSignal);\n const context = { seeds, ...traversed };\n const evidence = await hydrateEvidence(graph, context, options.evidence, options.abortSignal);\n return { ...context, evidence };\n}\n\nasync function vectorSearch(\n graph: Neo4jKnowledgeGraphBase,\n labels: readonly string[],\n indexName: string,\n vector: readonly number[],\n limit: number,\n entryRelationshipType?: string,\n abortSignal?: AbortSignal,\n): Promise<SearchHit[]> {\n const labelExpression = labels.map(quoteIdentifier).join(\"|\");\n const vectorFilter =\n graph instanceof ManagedNeo4jKnowledgeGraph && graph.namespace !== undefined\n ? ` WHERE seed.${quoteIdentifier(\"__anvia_namespace\")} = $namespace`\n : \"\";\n const postFilter = managedSearchPredicate(\n graph,\n \"seed\",\n entryRelationshipType === \"ANVIA_MENTIONS\",\n );\n const result = await graph.query(\n `CYPHER 25\nMATCH (seed:${labelExpression})\nSEARCH seed IN (VECTOR INDEX ${quoteIdentifier(indexName)} FOR $vector${vectorFilter} LIMIT $limit) SCORE AS score\n${postFilter}\nRETURN elementId(seed) AS elementId, labels(seed) AS labels, properties(seed) AS properties, score`,\n managedQueryParameters(graph, { vector, limit: int(limit) }),\n abortSignal,\n );\n return result.records.map((record) => ({ ...parseSearchHit(record), entryRelationshipType }));\n}\n\nasync function fulltextSearch(\n graph: Neo4jKnowledgeGraphBase,\n indexName: string,\n query: string,\n limit: number,\n entryRelationshipType?: string,\n abortSignal?: AbortSignal,\n): Promise<SearchHit[]> {\n const result = await graph.query(\n `CALL db.index.fulltext.queryNodes($indexName, $query, {limit: $limit}) YIELD node AS seed, score\n${managedSearchPredicate(graph, \"seed\", entryRelationshipType === \"ANVIA_MENTIONS\")}\nRETURN elementId(seed) AS elementId, labels(seed) AS labels, properties(seed) AS properties, score`,\n managedQueryParameters(graph, {\n indexName,\n query: scopedFulltextQuery(graph, query),\n limit: int(limit),\n }),\n abortSignal,\n );\n return result.records.map((record) => ({ ...parseSearchHit(record), entryRelationshipType }));\n}\n\nfunction parseSearchHit(record: Neo4jRecord): SearchHit {\n const elementId = record.get(\"elementId\");\n const labels = record.get(\"labels\");\n const properties = record.get(\"properties\");\n const score = record.get(\"score\");\n if (\n typeof elementId !== \"string\" ||\n !Array.isArray(labels) ||\n !labels.every((label) => typeof label === \"string\") ||\n typeof properties !== \"object\" ||\n properties === null ||\n typeof score !== \"number\" ||\n !Number.isFinite(score)\n ) {\n throw new TypeError(\"Neo4j search returned a malformed result.\");\n }\n return { elementId, labels, properties: properties as Record<string, unknown>, score };\n}\n\nfunction seedFromHit(hit: SearchHit, schema: Neo4jGraphSchema): Neo4jGraphContextSeed {\n const application = applicationProperties(hit.properties, \"Neo4j search seed\");\n const key =\n stringProperty(hit.properties, \"__anvia_key\") ??\n stringProperty(hit.properties, \"__anvia_id\") ??\n hit.elementId;\n const type = hit.labels.find((label) => label in schema.nodes) ?? hit.labels[0] ?? \"Node\";\n return {\n key,\n type,\n score: hit.score,\n properties: application,\n sourceChunkIds:\n hit.entryRelationshipType === \"ANVIA_MENTIONS\"\n ? [key]\n : stringArrayProperty(hit.properties, \"__anvia_source_chunk_ids\"),\n };\n}\n\nasync function hydrateEvidence(\n graph: Neo4jKnowledgeGraphBase,\n context: Pick<Neo4jGraphContext, \"seeds\" | \"nodes\" | \"relationships\">,\n options: Neo4jGraphEvidenceOptions,\n abortSignal?: AbortSignal,\n): Promise<Neo4jGraphEvidence[]> {\n if (options.type === \"none\") return [];\n if (!(graph instanceof ManagedNeo4jKnowledgeGraph)) {\n throw new TypeError(\"Chunk evidence requires a managed Neo4j knowledge graph.\");\n }\n const chunkIds: string[] = [];\n const seen = new Set<string>();\n for (const sourceChunkIds of [\n ...context.seeds.map((seed) => seed.sourceChunkIds),\n ...context.nodes.map((node) => node.sourceChunkIds),\n ...context.relationships.map((relationship) => relationship.sourceChunkIds),\n ]) {\n for (const chunkId of sourceChunkIds) {\n if (seen.has(chunkId)) continue;\n seen.add(chunkId);\n chunkIds.push(chunkId);\n if (chunkIds.length === options.maxChunks) break;\n }\n if (chunkIds.length === options.maxChunks) break;\n }\n if (chunkIds.length === 0) return [];\n throwIfAborted(abortSignal);\n const result = await graph.query(\n `MATCH (d:${quoteIdentifier(graph.resources.labels.document)})-[:${quoteIdentifier(\"ANVIA_HAS_CHUNK\")}]->(c:${quoteIdentifier(graph.resources.labels.chunk)})\nWHERE c.${quoteIdentifier(\"__anvia_id\")} IN $chunkIds\n ${tenantNodeAndPredicate(graph, \"d\")}${tenantNodeAndPredicate(graph, \"c\")}\nRETURN c.${quoteIdentifier(\"__anvia_id\")} AS chunkId,\n d.${quoteIdentifier(\"__anvia_id\")} AS documentId,\n c.${quoteIdentifier(\"__anvia_index\")} AS index,\n c.${quoteIdentifier(\"__anvia_text\")} AS text,\n properties(c) AS properties`,\n managedQueryParameters(graph, { chunkIds }),\n abortSignal,\n );\n const byId = new Map<string, Neo4jGraphEvidence>();\n for (const record of result.records) {\n const evidence = evidenceFromRecord(record);\n if (byId.has(evidence.chunkId)) {\n throw new TypeError(`Neo4j evidence returned duplicate chunk ${evidence.chunkId}.`);\n }\n byId.set(evidence.chunkId, evidence);\n }\n return chunkIds.map((chunkId) => {\n const evidence = byId.get(chunkId);\n if (evidence === undefined) {\n throw new Error(`Neo4j graph evidence references missing chunk ${chunkId}.`);\n }\n return evidence;\n });\n}\n\nfunction evidenceFromRecord(record: Neo4jRecord): Neo4jGraphEvidence {\n const chunkId = stringValue(record.get(\"chunkId\"), \"Neo4j evidence chunk id\");\n const documentId = stringValue(record.get(\"documentId\"), \"Neo4j evidence document id\");\n const index = safeIntegerValue(record.get(\"index\"), \"Neo4j evidence chunk index\");\n const text = stringValue(record.get(\"text\"), \"Neo4j evidence text\");\n const raw = record.get(\"properties\");\n if (typeof raw !== \"object\" || raw === null || Array.isArray(raw)) {\n throw new TypeError(\"Neo4j evidence properties must be an object.\");\n }\n return {\n chunkId,\n documentId,\n index,\n text,\n metadata: applicationProperties(raw as Record<string, unknown>, \"Neo4j evidence metadata\"),\n };\n}\n\nfunction safeIntegerValue(value: unknown, label: string): number {\n let number = value;\n if (isInt(value)) {\n number = undefined;\n if (value.inSafeRange()) {\n number = value.toNumber();\n }\n }\n if (typeof number !== \"number\" || !Number.isSafeInteger(number)) {\n throw new TypeError(`${label} must be a safe integer.`);\n }\n return number;\n}\n\nfunction vectorResults(\n results: SearchHit[],\n topK: number,\n minScore: number | undefined,\n): SearchHit[] {\n return results.filter((item) => minScore === undefined || item.score >= minScore).slice(0, topK);\n}\n\nasync function traverse<Schema extends Neo4jGraphSchema>(\n graph: Neo4jKnowledgeGraphBase<Schema>,\n seeds: readonly SearchHit[],\n options: RetrieveGraphContextOptions<Schema>[\"traversal\"],\n abortSignal?: AbortSignal,\n): Promise<{ nodes: Neo4jGraphContextNode[]; relationships: Neo4jGraphContextRelationship[] }> {\n const traversalSeedIds = new Set(\n seeds.filter((seed) => seed.entryRelationshipType === undefined).map((seed) => seed.elementId),\n );\n const entryGroups = groupBy(\n seeds.filter(\n (seed): seed is SearchHit & { entryRelationshipType: string } =>\n seed.entryRelationshipType !== undefined,\n ),\n (seed) => seed.entryRelationshipType,\n );\n for (const [relationshipType, group] of entryGroups) {\n const entries = await graph.query(\n `MATCH (seed) WHERE elementId(seed) IN $seedIds\n ${tenantNodePredicate(graph, \"seed\", \"AND\")}\nMATCH (seed)-[entryRelationship:${quoteIdentifier(relationshipType)}]->(entry)\nWHERE true${managedNodeAndPredicate(graph, \"entry\")}${tenantNodeAndPredicate(graph, \"entryRelationship\")}\nRETURN DISTINCT elementId(entry) AS elementId`,\n managedQueryParameters(graph, { seedIds: group.map((seed) => seed.elementId) }),\n abortSignal,\n );\n for (const record of entries.records) {\n traversalSeedIds.add(stringValue(record.get(\"elementId\"), \"Neo4j entry elementId\"));\n }\n }\n if (traversalSeedIds.size === 0) return { nodes: [], relationships: [] };\n const limitedSeedIds = [...traversalSeedIds].slice(0, options.maxNodes);\n const pattern = traversalPattern(options.direction, options.maxDepth);\n const pathLimit = Math.max(options.maxNodes, options.maxRelationships);\n const seedNodes = await graph.query(\n `MATCH (node) WHERE elementId(node) IN $seedIds\n ${managedNodePredicate(graph, \"node\", \"AND\")}\nRETURN {elementId: elementId(node), labels: labels(node), properties: properties(node)} AS node`,\n managedQueryParameters(graph, { seedIds: limitedSeedIds }),\n abortSignal,\n );\n const result = await graph.query(\n `MATCH (seed) WHERE elementId(seed) IN $seedIds\n ${managedNodePredicate(graph, \"seed\", \"AND\")}\nMATCH path = ${pattern}\nWHERE all(rel IN relationships(path) WHERE type(rel) IN $relationshipTypes${managedRelationshipAndPredicate(graph, \"rel\")})${managedPathAndPredicate(graph)}\nRETURN [item IN nodes(path) | {elementId: elementId(item), labels: labels(item), properties: properties(item)}] AS nodes,\n [item IN relationships(path) | {elementId: elementId(item), type: type(item), properties: properties(item), from: elementId(startNode(item)), to: elementId(endNode(item))}] AS relationships\nLIMIT $pathLimit`,\n managedQueryParameters(graph, {\n seedIds: limitedSeedIds,\n relationshipTypes: options.relationships,\n pathLimit: int(pathLimit),\n }),\n abortSignal,\n );\n const nodes = new Map<string, Neo4jGraphContextNode>();\n const nodeKeysByElementId = new Map<string, string>();\n const relationships = new Map<string, Neo4jGraphContextRelationship>();\n const seedNodesByElementId = new Map<string, Record<string, unknown>>();\n for (const record of seedNodes.records) {\n const value = record.get(\"node\");\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n throw new TypeError(\"Neo4j traversal returned a malformed seed node.\");\n }\n const map = value as Record<string, unknown>;\n seedNodesByElementId.set(stringValue(map.elementId, \"Neo4j seed node elementId\"), map);\n }\n const addNode = (value: Record<string, unknown>) => {\n const parsed = contextNode(value, graph.schema);\n const existing = nodes.get(parsed.node.key);\n if (existing === undefined && nodes.size >= options.maxNodes) return;\n if (existing === undefined) nodes.set(parsed.node.key, parsed.node);\n nodeKeysByElementId.set(parsed.elementId, parsed.node.key);\n };\n for (const elementId of limitedSeedIds) {\n const value = seedNodesByElementId.get(elementId);\n if (value !== undefined) addNode(value);\n }\n for (const record of result.records) {\n for (const value of listOfMaps(record.get(\"nodes\"), \"Neo4j traversal nodes\")) {\n addNode(value);\n }\n }\n for (const record of result.records) {\n for (const value of listOfMaps(record.get(\"relationships\"), \"Neo4j traversal relationships\")) {\n const relationship = contextRelationship(value, nodeKeysByElementId);\n if (\n relationship !== undefined &&\n !relationships.has(relationship.key) &&\n relationships.size < options.maxRelationships\n ) {\n relationships.set(relationship.key, relationship);\n }\n }\n }\n return { nodes: [...nodes.values()], relationships: [...relationships.values()] };\n}\n\nfunction traversalPattern(direction: \"outgoing\" | \"incoming\" | \"both\", maxDepth: number): string {\n if (direction === \"outgoing\") {\n return `(seed)-[*1..${maxDepth}]->(node)`;\n }\n if (direction === \"incoming\") {\n return `(seed)<-[*1..${maxDepth}]-(node)`;\n }\n return `(seed)-[*1..${maxDepth}]-(node)`;\n}\n\nfunction managedQueryParameters(\n graph: Neo4jKnowledgeGraphBase,\n parameters: Record<string, unknown>,\n): Record<string, unknown> {\n return managedScopeParameters(managedScope(graph), parameters);\n}\n\nfunction managedNodePredicate(\n graph: Neo4jKnowledgeGraphBase,\n variable: string,\n prefix: \"WHERE\" | \"AND\",\n): string {\n return managedScopePredicate(managedScope(graph), variable, prefix);\n}\n\nfunction managedSearchPredicate(\n graph: Neo4jKnowledgeGraphBase,\n variable: string,\n chunkSeed: boolean,\n): string {\n return chunkSeed && graph.namespace === undefined\n ? \"\"\n : managedNodePredicate(graph, variable, \"WHERE\");\n}\n\nfunction managedNodeAndPredicate(graph: Neo4jKnowledgeGraphBase, variable: string): string {\n return managedScopePredicate(managedScope(graph), variable, \" AND\");\n}\n\nfunction managedRelationshipAndPredicate(graph: Neo4jKnowledgeGraphBase, variable: string): string {\n return managedNodeAndPredicate(graph, variable);\n}\n\nfunction tenantNodePredicate(\n graph: Neo4jKnowledgeGraphBase,\n variable: string,\n prefix: \"WHERE\" | \"AND\",\n): string {\n const scope = managedScope(graph);\n return scope === undefined ? \"\" : tenantScopePredicate(scope, variable, prefix);\n}\n\nfunction tenantNodeAndPredicate(graph: Neo4jKnowledgeGraphBase, variable: string): string {\n const predicate = tenantNodePredicate(graph, variable, \"AND\");\n return predicate.length === 0 ? \"\" : ` ${predicate}`;\n}\n\nfunction managedPathAndPredicate(graph: Neo4jKnowledgeGraphBase): string {\n return managedPathPredicate(managedScope(graph), false);\n}\n\nfunction managedScope(graph: Neo4jKnowledgeGraphBase): Neo4jManagedScope | undefined {\n return graph instanceof ManagedNeo4jKnowledgeGraph\n ? { graph: graph.name, namespace: graph.namespace }\n : undefined;\n}\n\nfunction contextNode(\n value: Record<string, unknown>,\n schema: Neo4jGraphSchema,\n): { elementId: string; node: Neo4jGraphContextNode } {\n const labels = value.labels;\n const raw = value.properties;\n if (!Array.isArray(labels) || !labels.every((label) => typeof label === \"string\")) {\n throw new TypeError(\"Neo4j traversal returned malformed node labels.\");\n }\n if (typeof raw !== \"object\" || raw === null || Array.isArray(raw)) {\n throw new TypeError(\"Neo4j traversal returned malformed node properties.\");\n }\n const properties = applicationProperties(raw as Record<string, unknown>, \"Neo4j graph node\");\n const type = labels.find((label) => label in schema.nodes) ?? labels[0] ?? \"Node\";\n const definition = schema.nodes[type];\n const identity: Record<string, string | number | boolean> = {};\n if (definition !== undefined) {\n for (const property of definition.identity) {\n const item = properties[property];\n if (typeof item === \"string\" || typeof item === \"number\" || typeof item === \"boolean\") {\n identity[property] = item;\n }\n }\n }\n const elementId = stringValue(value.elementId, \"Neo4j node elementId\");\n return {\n elementId,\n node: {\n key: stringProperty(raw as Record<string, unknown>, \"__anvia_key\") ?? elementId,\n type,\n identity,\n properties,\n sourceChunkIds: stringArrayProperty(\n raw as Record<string, unknown>,\n \"__anvia_source_chunk_ids\",\n ),\n },\n };\n}\n\nfunction contextRelationship(\n value: Record<string, unknown>,\n nodeKeysByElementId: ReadonlyMap<string, string>,\n): Neo4jGraphContextRelationship | undefined {\n const raw = value.properties;\n if (typeof raw !== \"object\" || raw === null || Array.isArray(raw)) {\n throw new TypeError(\"Neo4j traversal returned malformed relationship properties.\");\n }\n const elementId = stringValue(value.elementId, \"Neo4j relationship elementId\");\n const fromElementId = stringValue(value.from, \"Neo4j relationship source\");\n const toElementId = stringValue(value.to, \"Neo4j relationship target\");\n const from = nodeKeysByElementId.get(fromElementId);\n const to = nodeKeysByElementId.get(toElementId);\n if (from === undefined || to === undefined) return undefined;\n return {\n key: stringProperty(raw as Record<string, unknown>, \"__anvia_key\") ?? elementId,\n type: stringValue(value.type, \"Neo4j relationship type\"),\n from,\n to,\n properties: applicationProperties(raw as Record<string, unknown>, \"Neo4j graph relationship\"),\n sourceChunkIds: stringArrayProperty(raw as Record<string, unknown>, \"__anvia_source_chunk_ids\"),\n };\n}\n\nfunction fuseResults(lists: readonly SearchHit[][], topK: number, rrfK: number): SearchHit[] {\n const fused = new Map<string, SearchHit>();\n for (const list of lists) {\n list.forEach((item, index) => {\n const score = 1 / (rrfK + index + 1);\n const current = fused.get(item.elementId);\n fused.set(item.elementId, { ...item, score: (current?.score ?? 0) + score });\n });\n }\n return [...fused.values()].sort((left, right) => right.score - left.score).slice(0, topK);\n}\n\nfunction validateSearch(search: RetrieveGraphContextOptions<Neo4jGraphSchema>[\"search\"]): void {\n positiveInteger(search.topK, \"Neo4j graph search topK\");\n if (search.seeds.length === 0 || new Set(search.seeds).size !== search.seeds.length) {\n throw new TypeError(\"Neo4j graph search requires unique seed names.\");\n }\n if (search.type === \"vector\") {\n if (search.seeds.length !== 1)\n throw new TypeError(\n \"Vector graph search accepts exactly one seed; use hybrid search to fuse multiple seeds.\",\n );\n finiteScore(search.minScore, \"Neo4j graph search minScore\");\n } else {\n positiveInteger(search.candidatesPerSeed, \"Neo4j hybrid candidatesPerSeed\");\n positiveInteger(search.rrfK, \"Neo4j hybrid rrfK\");\n }\n}\n\nfunction validateEvidence(\n capability: \"none\" | \"chunks\",\n evidence: Neo4jGraphEvidenceOptions,\n): void {\n if (typeof evidence !== \"object\" || evidence === null) {\n throw new TypeError(\"Neo4j graph retrieval requires an explicit evidence mode.\");\n }\n if (evidence.type === \"none\") return;\n if (evidence.type !== \"chunks\") {\n throw new TypeError(\"Unknown Neo4j graph evidence mode.\");\n }\n positiveInteger(evidence.maxChunks, \"Neo4j graph evidence maxChunks\");\n if (capability !== \"chunks\") {\n throw new TypeError(\"Chunk evidence requires a managed Neo4j knowledge graph.\");\n }\n}\n\nfunction validateTraversal(\n schema: Neo4jGraphSchema,\n traversal: RetrieveGraphContextOptions<Neo4jGraphSchema>[\"traversal\"],\n): void {\n if (\n traversal.direction !== \"outgoing\" &&\n traversal.direction !== \"incoming\" &&\n traversal.direction !== \"both\"\n ) {\n throw new TypeError(\"Neo4j traversal direction must be outgoing, incoming, or both.\");\n }\n positiveInteger(traversal.maxDepth, \"Neo4j traversal maxDepth\", 8);\n positiveInteger(traversal.maxNodes, \"Neo4j traversal maxNodes\");\n positiveInteger(traversal.maxRelationships, \"Neo4j traversal maxRelationships\");\n if (\n traversal.relationships.length === 0 ||\n new Set(traversal.relationships).size !== traversal.relationships.length\n ) {\n throw new TypeError(\"Neo4j traversal requires unique relationship types.\");\n }\n for (const type of traversal.relationships) {\n if (!(type in schema.relationships))\n throw new TypeError(`Neo4j traversal references unknown relationship type ${type}.`);\n }\n}\n\nfunction applicationProperties(value: Record<string, unknown>, label: string) {\n return strictProperties(\n Object.fromEntries(Object.entries(value).filter(([key]) => !key.startsWith(\"__anvia_\"))),\n label,\n );\n}\n\nfunction stringProperty(value: Record<string, unknown>, property: string): string | undefined {\n const item = value[property];\n if (item === undefined) return undefined;\n return stringValue(item, `Neo4j property ${property}`);\n}\n\nfunction stringArrayProperty(value: Record<string, unknown>, property: string): string[] {\n const item = value[property];\n if (item === undefined) return [];\n if (!Array.isArray(item) || !item.every((entry) => typeof entry === \"string\")) {\n throw new TypeError(`Neo4j property ${property} must be a string array.`);\n }\n return [...item];\n}\n\nfunction stringValue(value: unknown, label: string): string {\n if (typeof value !== \"string\") throw new TypeError(`${label} must be a string.`);\n return value;\n}\n\nfunction listOfMaps(value: unknown, label: string): Record<string, unknown>[] {\n if (\n !Array.isArray(value) ||\n !value.every((item) => typeof item === \"object\" && item !== null && !Array.isArray(item))\n ) {\n throw new TypeError(`${label} must be an array of objects.`);\n }\n return value as Record<string, unknown>[];\n}\n\nfunction escapeLucene(value: string): string {\n const specialCharacters = new Set('+-&|!(){}[]^\"~*?:\\\\/');\n let escaped = \"\";\n for (const character of value) {\n escaped += specialCharacters.has(character) ? `\\\\${character}` : character;\n }\n return escaped;\n}\n\nfunction scopedFulltextQuery(graph: Neo4jKnowledgeGraphBase, value: string): string {\n const query = escapeLucene(value);\n return graph instanceof ManagedNeo4jKnowledgeGraph && graph.namespace !== undefined\n ? `(${query}) AND __anvia_namespace:${escapeLucene(graph.namespace)}`\n : query;\n}\n\nfunction groupBy<Value, Key>(\n values: readonly Value[],\n keyFor: (value: Value) => Key,\n): Map<Key, Value[]> {\n const groups = new Map<Key, Value[]>();\n for (const value of values) {\n const key = keyFor(value);\n const group = groups.get(key);\n if (group === undefined) groups.set(key, [value]);\n else group.push(value);\n }\n return groups;\n}\n"],"mappings":";;;;;;;;;;;;;;;AAAA,SAAS,iBAAiB;AAC1B,SAAS,KAAK,aAAyC;AAmCvD,eAAsB,qBACpB,SAC4B;AAC5B,MAAI,EAAE,QAAQ,iBAAiB,0BAA0B;AACvD,UAAM,IAAI,UAAU,qEAAqE;AAAA,EAC3F;AACA,MAAI,OAAO,QAAQ,UAAU,YAAY,QAAQ,MAAM,KAAK,EAAE,WAAW,GAAG;AAC1E,UAAM,IAAI,UAAU,mDAAmD;AAAA,EACzE;AACA,iBAAe,QAAQ,MAAM;AAC7B,oBAAkB,QAAQ,MAAM,QAAQ,QAAQ,SAAS;AACzD,mBAAiB,QAAQ,MAAM,oBAAoB,QAAQ,QAAQ;AACnE,iBAAe,QAAQ,WAAW;AAClC,QAAM,QAAQ,QAAQ;AACtB,QAAM,gBAAgB,QAAQ,OAAO,MAAM,IAAI,CAAC,UAAU,EAAE,MAAM,MAAM,MAAM,KAAK,IAAI,EAAE,EAAE;AAC3F,QAAM,qBAAqB,cAAc,CAAC,GAAG,KAAK,YAAY;AAC9D,MACE,uBAAuB,UACvB,cAAc,KAAK,CAAC,SAAS,KAAK,KAAK,YAAY,eAAe,kBAAkB,GACpF;AACA,UAAM,IAAI,UAAU,iEAAiE;AAAA,EACvF;AACA,MAAI,QAAQ,MAAM,eAAe,UAAa,QAAQ,MAAM,eAAe,oBAAoB;AAC7F,UAAM,IAAI;AAAA,MACR,8BAA8B,QAAQ,MAAM,UAAU,wCAAwC,kBAAkB;AAAA,IAClH;AAAA,EACF;AACA,MAAI,QAAQ,OAAO,SAAS,UAAU;AACpC,eAAW,EAAE,MAAM,KAAK,KAAK,eAAe;AAC1C,UAAI,KAAK,kBAAkB,QAAW;AACpC,cAAM,IAAI,UAAU,oBAAoB,IAAI,sCAAsC;AAAA,MACpF;AAAA,IACF;AAAA,EACF;AACA,QAAM,EAAE,UAAU,IAAI,MAAM,UAAU;AAAA,IACpC,OAAO,QAAQ;AAAA,IACf,MAAM,QAAQ;AAAA,IACd,SAAS,QAAQ;AAAA,IACjB,aAAa,QAAQ;AAAA,EACvB,CAAC;AACD,MAAI,UAAU,OAAO,WAAW,oBAAoB;AAClD,UAAM,IAAI;AAAA,MACR,8BAA8B,UAAU,OAAO,MAAM,wCAAwC,kBAAkB;AAAA,IACjH;AAAA,EACF;AAEA,QAAM,cAA6B,CAAC;AACpC,aAAW,EAAE,KAAK,KAAK,eAAe;AACpC,UAAM,QACJ,QAAQ,OAAO,SAAS,WAAW,QAAQ,OAAO,oBAAoB,QAAQ,OAAO;AACvF,gBAAY;AAAA,MACV,MAAM;AAAA,QACJ;AAAA,QACA,KAAK;AAAA,QACL,KAAK,YAAY;AAAA,QACjB,UAAU;AAAA,QACV;AAAA,QACA,KAAK;AAAA,QACL,QAAQ;AAAA,MACV;AAAA,IACF;AACA,QAAI,QAAQ,OAAO,SAAS,UAAU;AACpC,YAAM,gBAAgB,KAAK;AAC3B,UAAI,kBAAkB,QAAW;AAC/B,cAAM,IAAI,UAAU,0DAA0D;AAAA,MAChF;AACA,kBAAY;AAAA,QACV,MAAM;AAAA,UACJ;AAAA,UACA,cAAc;AAAA,UACd,QAAQ;AAAA,UACR;AAAA,UACA,KAAK;AAAA,UACL,QAAQ;AAAA,QACV;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,QAAM,OACJ,QAAQ,OAAO,SAAS,WACpB,YAAY,aAAa,QAAQ,OAAO,MAAM,QAAQ,OAAO,IAAI,IACjE,cAAc,YAAY,CAAC,KAAK,CAAC,GAAG,QAAQ,OAAO,MAAM,QAAQ,OAAO,QAAQ;AACtF,iBAAe,QAAQ,WAAW;AAClC,QAAM,QAAQ,KAAK,IAAI,CAAC,QAAQ,YAAY,KAAK,QAAQ,MAAM,MAAM,CAAC;AACtE,QAAM,YACJ,KAAK,WAAW,IACZ,EAAE,OAAO,CAAC,GAAG,eAAe,CAAC,EAAE,IAC/B,MAAM,SAAS,OAAO,MAAM,QAAQ,WAAW,QAAQ,WAAW;AACxE,QAAM,UAAU,EAAE,OAAO,GAAG,UAAU;AACtC,QAAM,WAAW,MAAM,gBAAgB,OAAO,SAAS,QAAQ,UAAU,QAAQ,WAAW;AAC5F,SAAO,EAAE,GAAG,SAAS,SAAS;AAChC;AAEA,eAAe,aACb,OACA,QACA,WACA,QACA,OACA,uBACA,aACsB;AACtB,QAAM,kBAAkB,OAAO,IAAI,eAAe,EAAE,KAAK,GAAG;AAC5D,QAAM,eACJ,iBAAiB,8BAA8B,MAAM,cAAc,SAC/D,eAAe,gBAAgB,mBAAmB,CAAC,kBACnD;AACN,QAAM,aAAa;AAAA,IACjB;AAAA,IACA;AAAA,IACA,0BAA0B;AAAA,EAC5B;AACA,QAAM,SAAS,MAAM,MAAM;AAAA,IACzB;AAAA,cACU,eAAe;AAAA,+BACE,gBAAgB,SAAS,CAAC,eAAe,YAAY;AAAA,EAClF,UAAU;AAAA;AAAA,IAER,uBAAuB,OAAO,EAAE,QAAQ,OAAO,IAAI,KAAK,EAAE,CAAC;AAAA,IAC3D;AAAA,EACF;AACA,SAAO,OAAO,QAAQ,IAAI,CAAC,YAAY,EAAE,GAAG,eAAe,MAAM,GAAG,sBAAsB,EAAE;AAC9F;AAEA,eAAe,eACb,OACA,WACA,OACA,OACA,uBACA,aACsB;AACtB,QAAM,SAAS,MAAM,MAAM;AAAA,IACzB;AAAA,EACF,uBAAuB,OAAO,QAAQ,0BAA0B,gBAAgB,CAAC;AAAA;AAAA,IAE/E,uBAAuB,OAAO;AAAA,MAC5B;AAAA,MACA,OAAO,oBAAoB,OAAO,KAAK;AAAA,MACvC,OAAO,IAAI,KAAK;AAAA,IAClB,CAAC;AAAA,IACD;AAAA,EACF;AACA,SAAO,OAAO,QAAQ,IAAI,CAAC,YAAY,EAAE,GAAG,eAAe,MAAM,GAAG,sBAAsB,EAAE;AAC9F;AAEA,SAAS,eAAe,QAAgC;AACtD,QAAM,YAAY,OAAO,IAAI,WAAW;AACxC,QAAM,SAAS,OAAO,IAAI,QAAQ;AAClC,QAAM,aAAa,OAAO,IAAI,YAAY;AAC1C,QAAM,QAAQ,OAAO,IAAI,OAAO;AAChC,MACE,OAAO,cAAc,YACrB,CAAC,MAAM,QAAQ,MAAM,KACrB,CAAC,OAAO,MAAM,CAAC,UAAU,OAAO,UAAU,QAAQ,KAClD,OAAO,eAAe,YACtB,eAAe,QACf,OAAO,UAAU,YACjB,CAAC,OAAO,SAAS,KAAK,GACtB;AACA,UAAM,IAAI,UAAU,2CAA2C;AAAA,EACjE;AACA,SAAO,EAAE,WAAW,QAAQ,YAAmD,MAAM;AACvF;AAEA,SAAS,YAAY,KAAgB,QAAiD;AACpF,QAAM,cAAc,sBAAsB,IAAI,YAAY,mBAAmB;AAC7E,QAAM,MACJ,eAAe,IAAI,YAAY,aAAa,KAC5C,eAAe,IAAI,YAAY,YAAY,KAC3C,IAAI;AACN,QAAM,OAAO,IAAI,OAAO,KAAK,CAAC,UAAU,SAAS,OAAO,KAAK,KAAK,IAAI,OAAO,CAAC,KAAK;AACnF,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,OAAO,IAAI;AAAA,IACX,YAAY;AAAA,IACZ,gBACE,IAAI,0BAA0B,mBAC1B,CAAC,GAAG,IACJ,oBAAoB,IAAI,YAAY,0BAA0B;AAAA,EACtE;AACF;AAEA,eAAe,gBACb,OACA,SACA,SACA,aAC+B;AAC/B,MAAI,QAAQ,SAAS,OAAQ,QAAO,CAAC;AACrC,MAAI,EAAE,iBAAiB,6BAA6B;AAClD,UAAM,IAAI,UAAU,0DAA0D;AAAA,EAChF;AACA,QAAM,WAAqB,CAAC;AAC5B,QAAM,OAAO,oBAAI,IAAY;AAC7B,aAAW,kBAAkB;AAAA,IAC3B,GAAG,QAAQ,MAAM,IAAI,CAAC,SAAS,KAAK,cAAc;AAAA,IAClD,GAAG,QAAQ,MAAM,IAAI,CAAC,SAAS,KAAK,cAAc;AAAA,IAClD,GAAG,QAAQ,cAAc,IAAI,CAAC,iBAAiB,aAAa,cAAc;AAAA,EAC5E,GAAG;AACD,eAAW,WAAW,gBAAgB;AACpC,UAAI,KAAK,IAAI,OAAO,EAAG;AACvB,WAAK,IAAI,OAAO;AAChB,eAAS,KAAK,OAAO;AACrB,UAAI,SAAS,WAAW,QAAQ,UAAW;AAAA,IAC7C;AACA,QAAI,SAAS,WAAW,QAAQ,UAAW;AAAA,EAC7C;AACA,MAAI,SAAS,WAAW,EAAG,QAAO,CAAC;AACnC,iBAAe,WAAW;AAC1B,QAAM,SAAS,MAAM,MAAM;AAAA,IACzB,YAAY,gBAAgB,MAAM,UAAU,OAAO,QAAQ,CAAC,OAAO,gBAAgB,iBAAiB,CAAC,SAAS,gBAAgB,MAAM,UAAU,OAAO,KAAK,CAAC;AAAA,UACrJ,gBAAgB,YAAY,CAAC;AAAA,IACnC,uBAAuB,OAAO,GAAG,CAAC,GAAG,uBAAuB,OAAO,GAAG,CAAC;AAAA,WAChE,gBAAgB,YAAY,CAAC;AAAA,WAC7B,gBAAgB,YAAY,CAAC;AAAA,WAC7B,gBAAgB,eAAe,CAAC;AAAA,WAChC,gBAAgB,cAAc,CAAC;AAAA;AAAA,IAEtC,uBAAuB,OAAO,EAAE,SAAS,CAAC;AAAA,IAC1C;AAAA,EACF;AACA,QAAM,OAAO,oBAAI,IAAgC;AACjD,aAAW,UAAU,OAAO,SAAS;AACnC,UAAM,WAAW,mBAAmB,MAAM;AAC1C,QAAI,KAAK,IAAI,SAAS,OAAO,GAAG;AAC9B,YAAM,IAAI,UAAU,2CAA2C,SAAS,OAAO,GAAG;AAAA,IACpF;AACA,SAAK,IAAI,SAAS,SAAS,QAAQ;AAAA,EACrC;AACA,SAAO,SAAS,IAAI,CAAC,YAAY;AAC/B,UAAM,WAAW,KAAK,IAAI,OAAO;AACjC,QAAI,aAAa,QAAW;AAC1B,YAAM,IAAI,MAAM,iDAAiD,OAAO,GAAG;AAAA,IAC7E;AACA,WAAO;AAAA,EACT,CAAC;AACH;AAEA,SAAS,mBAAmB,QAAyC;AACnE,QAAM,UAAU,YAAY,OAAO,IAAI,SAAS,GAAG,yBAAyB;AAC5E,QAAM,aAAa,YAAY,OAAO,IAAI,YAAY,GAAG,4BAA4B;AACrF,QAAM,QAAQ,iBAAiB,OAAO,IAAI,OAAO,GAAG,4BAA4B;AAChF,QAAM,OAAO,YAAY,OAAO,IAAI,MAAM,GAAG,qBAAqB;AAClE,QAAM,MAAM,OAAO,IAAI,YAAY;AACnC,MAAI,OAAO,QAAQ,YAAY,QAAQ,QAAQ,MAAM,QAAQ,GAAG,GAAG;AACjE,UAAM,IAAI,UAAU,8CAA8C;AAAA,EACpE;AACA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,UAAU,sBAAsB,KAAgC,yBAAyB;AAAA,EAC3F;AACF;AAEA,SAAS,iBAAiB,OAAgB,OAAuB;AAC/D,MAAI,SAAS;AACb,MAAI,MAAM,KAAK,GAAG;AAChB,aAAS;AACT,QAAI,MAAM,YAAY,GAAG;AACvB,eAAS,MAAM,SAAS;AAAA,IAC1B;AAAA,EACF;AACA,MAAI,OAAO,WAAW,YAAY,CAAC,OAAO,cAAc,MAAM,GAAG;AAC/D,UAAM,IAAI,UAAU,GAAG,KAAK,0BAA0B;AAAA,EACxD;AACA,SAAO;AACT;AAEA,SAAS,cACP,SACA,MACA,UACa;AACb,SAAO,QAAQ,OAAO,CAAC,SAAS,aAAa,UAAa,KAAK,SAAS,QAAQ,EAAE,MAAM,GAAG,IAAI;AACjG;AAEA,eAAe,SACb,OACA,OACA,SACA,aAC6F;AAC7F,QAAM,mBAAmB,IAAI;AAAA,IAC3B,MAAM,OAAO,CAAC,SAAS,KAAK,0BAA0B,MAAS,EAAE,IAAI,CAAC,SAAS,KAAK,SAAS;AAAA,EAC/F;AACA,QAAM,cAAc;AAAA,IAClB,MAAM;AAAA,MACJ,CAAC,SACC,KAAK,0BAA0B;AAAA,IACnC;AAAA,IACA,CAAC,SAAS,KAAK;AAAA,EACjB;AACA,aAAW,CAAC,kBAAkB,KAAK,KAAK,aAAa;AACnD,UAAM,UAAU,MAAM,MAAM;AAAA,MAC1B;AAAA,IACF,oBAAoB,OAAO,QAAQ,KAAK,CAAC;AAAA,kCACX,gBAAgB,gBAAgB,CAAC;AAAA,YACvD,wBAAwB,OAAO,OAAO,CAAC,GAAG,uBAAuB,OAAO,mBAAmB,CAAC;AAAA;AAAA,MAElG,uBAAuB,OAAO,EAAE,SAAS,MAAM,IAAI,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;AAAA,MAC9E;AAAA,IACF;AACA,eAAW,UAAU,QAAQ,SAAS;AACpC,uBAAiB,IAAI,YAAY,OAAO,IAAI,WAAW,GAAG,uBAAuB,CAAC;AAAA,IACpF;AAAA,EACF;AACA,MAAI,iBAAiB,SAAS,EAAG,QAAO,EAAE,OAAO,CAAC,GAAG,eAAe,CAAC,EAAE;AACvE,QAAM,iBAAiB,CAAC,GAAG,gBAAgB,EAAE,MAAM,GAAG,QAAQ,QAAQ;AACtE,QAAM,UAAU,iBAAiB,QAAQ,WAAW,QAAQ,QAAQ;AACpE,QAAM,YAAY,KAAK,IAAI,QAAQ,UAAU,QAAQ,gBAAgB;AACrE,QAAM,YAAY,MAAM,MAAM;AAAA,IAC5B;AAAA,IACA,qBAAqB,OAAO,QAAQ,KAAK,CAAC;AAAA;AAAA,IAE1C,uBAAuB,OAAO,EAAE,SAAS,eAAe,CAAC;AAAA,IACzD;AAAA,EACF;AACA,QAAM,SAAS,MAAM,MAAM;AAAA,IACzB;AAAA,IACA,qBAAqB,OAAO,QAAQ,KAAK,CAAC;AAAA,eAC/B,OAAO;AAAA,4EACsD,gCAAgC,OAAO,KAAK,CAAC,IAAI,wBAAwB,KAAK,CAAC;AAAA;AAAA;AAAA;AAAA,IAIvJ,uBAAuB,OAAO;AAAA,MAC5B,SAAS;AAAA,MACT,mBAAmB,QAAQ;AAAA,MAC3B,WAAW,IAAI,SAAS;AAAA,IAC1B,CAAC;AAAA,IACD;AAAA,EACF;AACA,QAAM,QAAQ,oBAAI,IAAmC;AACrD,QAAM,sBAAsB,oBAAI,IAAoB;AACpD,QAAM,gBAAgB,oBAAI,IAA2C;AACrE,QAAM,uBAAuB,oBAAI,IAAqC;AACtE,aAAW,UAAU,UAAU,SAAS;AACtC,UAAM,QAAQ,OAAO,IAAI,MAAM;AAC/B,QAAI,OAAO,UAAU,YAAY,UAAU,QAAQ,MAAM,QAAQ,KAAK,GAAG;AACvE,YAAM,IAAI,UAAU,iDAAiD;AAAA,IACvE;AACA,UAAM,MAAM;AACZ,yBAAqB,IAAI,YAAY,IAAI,WAAW,2BAA2B,GAAG,GAAG;AAAA,EACvF;AACA,QAAM,UAAU,CAAC,UAAmC;AAClD,UAAM,SAAS,YAAY,OAAO,MAAM,MAAM;AAC9C,UAAM,WAAW,MAAM,IAAI,OAAO,KAAK,GAAG;AAC1C,QAAI,aAAa,UAAa,MAAM,QAAQ,QAAQ,SAAU;AAC9D,QAAI,aAAa,OAAW,OAAM,IAAI,OAAO,KAAK,KAAK,OAAO,IAAI;AAClE,wBAAoB,IAAI,OAAO,WAAW,OAAO,KAAK,GAAG;AAAA,EAC3D;AACA,aAAW,aAAa,gBAAgB;AACtC,UAAM,QAAQ,qBAAqB,IAAI,SAAS;AAChD,QAAI,UAAU,OAAW,SAAQ,KAAK;AAAA,EACxC;AACA,aAAW,UAAU,OAAO,SAAS;AACnC,eAAW,SAAS,WAAW,OAAO,IAAI,OAAO,GAAG,uBAAuB,GAAG;AAC5E,cAAQ,KAAK;AAAA,IACf;AAAA,EACF;AACA,aAAW,UAAU,OAAO,SAAS;AACnC,eAAW,SAAS,WAAW,OAAO,IAAI,eAAe,GAAG,+BAA+B,GAAG;AAC5F,YAAM,eAAe,oBAAoB,OAAO,mBAAmB;AACnE,UACE,iBAAiB,UACjB,CAAC,cAAc,IAAI,aAAa,GAAG,KACnC,cAAc,OAAO,QAAQ,kBAC7B;AACA,sBAAc,IAAI,aAAa,KAAK,YAAY;AAAA,MAClD;AAAA,IACF;AAAA,EACF;AACA,SAAO,EAAE,OAAO,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,eAAe,CAAC,GAAG,cAAc,OAAO,CAAC,EAAE;AAClF;AAEA,SAAS,iBAAiB,WAA6C,UAA0B;AAC/F,MAAI,cAAc,YAAY;AAC5B,WAAO,eAAe,QAAQ;AAAA,EAChC;AACA,MAAI,cAAc,YAAY;AAC5B,WAAO,gBAAgB,QAAQ;AAAA,EACjC;AACA,SAAO,eAAe,QAAQ;AAChC;AAEA,SAAS,uBACP,OACA,YACyB;AACzB,SAAO,uBAAuB,aAAa,KAAK,GAAG,UAAU;AAC/D;AAEA,SAAS,qBACP,OACA,UACA,QACQ;AACR,SAAO,sBAAsB,aAAa,KAAK,GAAG,UAAU,MAAM;AACpE;AAEA,SAAS,uBACP,OACA,UACA,WACQ;AACR,SAAO,aAAa,MAAM,cAAc,SACpC,KACA,qBAAqB,OAAO,UAAU,OAAO;AACnD;AAEA,SAAS,wBAAwB,OAAgC,UAA0B;AACzF,SAAO,sBAAsB,aAAa,KAAK,GAAG,UAAU,MAAM;AACpE;AAEA,SAAS,gCAAgC,OAAgC,UAA0B;AACjG,SAAO,wBAAwB,OAAO,QAAQ;AAChD;AAEA,SAAS,oBACP,OACA,UACA,QACQ;AACR,QAAM,QAAQ,aAAa,KAAK;AAChC,SAAO,UAAU,SAAY,KAAK,qBAAqB,OAAO,UAAU,MAAM;AAChF;AAEA,SAAS,uBAAuB,OAAgC,UAA0B;AACxF,QAAM,YAAY,oBAAoB,OAAO,UAAU,KAAK;AAC5D,SAAO,UAAU,WAAW,IAAI,KAAK,IAAI,SAAS;AACpD;AAEA,SAAS,wBAAwB,OAAwC;AACvE,SAAO,qBAAqB,aAAa,KAAK,GAAG,KAAK;AACxD;AAEA,SAAS,aAAa,OAA+D;AACnF,SAAO,iBAAiB,6BACpB,EAAE,OAAO,MAAM,MAAM,WAAW,MAAM,UAAU,IAChD;AACN;AAEA,SAAS,YACP,OACA,QACoD;AACpD,QAAM,SAAS,MAAM;AACrB,QAAM,MAAM,MAAM;AAClB,MAAI,CAAC,MAAM,QAAQ,MAAM,KAAK,CAAC,OAAO,MAAM,CAAC,UAAU,OAAO,UAAU,QAAQ,GAAG;AACjF,UAAM,IAAI,UAAU,iDAAiD;AAAA,EACvE;AACA,MAAI,OAAO,QAAQ,YAAY,QAAQ,QAAQ,MAAM,QAAQ,GAAG,GAAG;AACjE,UAAM,IAAI,UAAU,qDAAqD;AAAA,EAC3E;AACA,QAAM,aAAa,sBAAsB,KAAgC,kBAAkB;AAC3F,QAAM,OAAO,OAAO,KAAK,CAAC,UAAU,SAAS,OAAO,KAAK,KAAK,OAAO,CAAC,KAAK;AAC3E,QAAM,aAAa,OAAO,MAAM,IAAI;AACpC,QAAM,WAAsD,CAAC;AAC7D,MAAI,eAAe,QAAW;AAC5B,eAAW,YAAY,WAAW,UAAU;AAC1C,YAAM,OAAO,WAAW,QAAQ;AAChC,UAAI,OAAO,SAAS,YAAY,OAAO,SAAS,YAAY,OAAO,SAAS,WAAW;AACrF,iBAAS,QAAQ,IAAI;AAAA,MACvB;AAAA,IACF;AAAA,EACF;AACA,QAAM,YAAY,YAAY,MAAM,WAAW,sBAAsB;AACrE,SAAO;AAAA,IACL;AAAA,IACA,MAAM;AAAA,MACJ,KAAK,eAAe,KAAgC,aAAa,KAAK;AAAA,MACtE;AAAA,MACA;AAAA,MACA;AAAA,MACA,gBAAgB;AAAA,QACd;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;AAEA,SAAS,oBACP,OACA,qBAC2C;AAC3C,QAAM,MAAM,MAAM;AAClB,MAAI,OAAO,QAAQ,YAAY,QAAQ,QAAQ,MAAM,QAAQ,GAAG,GAAG;AACjE,UAAM,IAAI,UAAU,6DAA6D;AAAA,EACnF;AACA,QAAM,YAAY,YAAY,MAAM,WAAW,8BAA8B;AAC7E,QAAM,gBAAgB,YAAY,MAAM,MAAM,2BAA2B;AACzE,QAAM,cAAc,YAAY,MAAM,IAAI,2BAA2B;AACrE,QAAM,OAAO,oBAAoB,IAAI,aAAa;AAClD,QAAM,KAAK,oBAAoB,IAAI,WAAW;AAC9C,MAAI,SAAS,UAAa,OAAO,OAAW,QAAO;AACnD,SAAO;AAAA,IACL,KAAK,eAAe,KAAgC,aAAa,KAAK;AAAA,IACtE,MAAM,YAAY,MAAM,MAAM,yBAAyB;AAAA,IACvD;AAAA,IACA;AAAA,IACA,YAAY,sBAAsB,KAAgC,0BAA0B;AAAA,IAC5F,gBAAgB,oBAAoB,KAAgC,0BAA0B;AAAA,EAChG;AACF;AAEA,SAAS,YAAY,OAA+B,MAAc,MAA2B;AAC3F,QAAM,QAAQ,oBAAI,IAAuB;AACzC,aAAW,QAAQ,OAAO;AACxB,SAAK,QAAQ,CAAC,MAAM,UAAU;AAC5B,YAAM,QAAQ,KAAK,OAAO,QAAQ;AAClC,YAAM,UAAU,MAAM,IAAI,KAAK,SAAS;AACxC,YAAM,IAAI,KAAK,WAAW,EAAE,GAAG,MAAM,QAAQ,SAAS,SAAS,KAAK,MAAM,CAAC;AAAA,IAC7E,CAAC;AAAA,EACH;AACA,SAAO,CAAC,GAAG,MAAM,OAAO,CAAC,EAAE,KAAK,CAAC,MAAM,UAAU,MAAM,QAAQ,KAAK,KAAK,EAAE,MAAM,GAAG,IAAI;AAC1F;AAEA,SAAS,eAAe,QAAuE;AAC7F,kBAAgB,OAAO,MAAM,yBAAyB;AACtD,MAAI,OAAO,MAAM,WAAW,KAAK,IAAI,IAAI,OAAO,KAAK,EAAE,SAAS,OAAO,MAAM,QAAQ;AACnF,UAAM,IAAI,UAAU,gDAAgD;AAAA,EACtE;AACA,MAAI,OAAO,SAAS,UAAU;AAC5B,QAAI,OAAO,MAAM,WAAW;AAC1B,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AACF,gBAAY,OAAO,UAAU,6BAA6B;AAAA,EAC5D,OAAO;AACL,oBAAgB,OAAO,mBAAmB,gCAAgC;AAC1E,oBAAgB,OAAO,MAAM,mBAAmB;AAAA,EAClD;AACF;AAEA,SAAS,iBACP,YACA,UACM;AACN,MAAI,OAAO,aAAa,YAAY,aAAa,MAAM;AACrD,UAAM,IAAI,UAAU,2DAA2D;AAAA,EACjF;AACA,MAAI,SAAS,SAAS,OAAQ;AAC9B,MAAI,SAAS,SAAS,UAAU;AAC9B,UAAM,IAAI,UAAU,oCAAoC;AAAA,EAC1D;AACA,kBAAgB,SAAS,WAAW,gCAAgC;AACpE,MAAI,eAAe,UAAU;AAC3B,UAAM,IAAI,UAAU,0DAA0D;AAAA,EAChF;AACF;AAEA,SAAS,kBACP,QACA,WACM;AACN,MACE,UAAU,cAAc,cACxB,UAAU,cAAc,cACxB,UAAU,cAAc,QACxB;AACA,UAAM,IAAI,UAAU,gEAAgE;AAAA,EACtF;AACA,kBAAgB,UAAU,UAAU,4BAA4B,CAAC;AACjE,kBAAgB,UAAU,UAAU,0BAA0B;AAC9D,kBAAgB,UAAU,kBAAkB,kCAAkC;AAC9E,MACE,UAAU,cAAc,WAAW,KACnC,IAAI,IAAI,UAAU,aAAa,EAAE,SAAS,UAAU,cAAc,QAClE;AACA,UAAM,IAAI,UAAU,qDAAqD;AAAA,EAC3E;AACA,aAAW,QAAQ,UAAU,eAAe;AAC1C,QAAI,EAAE,QAAQ,OAAO;AACnB,YAAM,IAAI,UAAU,wDAAwD,IAAI,GAAG;AAAA,EACvF;AACF;AAEA,SAAS,sBAAsB,OAAgC,OAAe;AAC5E,SAAO;AAAA,IACL,OAAO,YAAY,OAAO,QAAQ,KAAK,EAAE,OAAO,CAAC,CAAC,GAAG,MAAM,CAAC,IAAI,WAAW,UAAU,CAAC,CAAC;AAAA,IACvF;AAAA,EACF;AACF;AAEA,SAAS,eAAe,OAAgC,UAAsC;AAC5F,QAAM,OAAO,MAAM,QAAQ;AAC3B,MAAI,SAAS,OAAW,QAAO;AAC/B,SAAO,YAAY,MAAM,kBAAkB,QAAQ,EAAE;AACvD;AAEA,SAAS,oBAAoB,OAAgC,UAA4B;AACvF,QAAM,OAAO,MAAM,QAAQ;AAC3B,MAAI,SAAS,OAAW,QAAO,CAAC;AAChC,MAAI,CAAC,MAAM,QAAQ,IAAI,KAAK,CAAC,KAAK,MAAM,CAAC,UAAU,OAAO,UAAU,QAAQ,GAAG;AAC7E,UAAM,IAAI,UAAU,kBAAkB,QAAQ,0BAA0B;AAAA,EAC1E;AACA,SAAO,CAAC,GAAG,IAAI;AACjB;AAEA,SAAS,YAAY,OAAgB,OAAuB;AAC1D,MAAI,OAAO,UAAU,SAAU,OAAM,IAAI,UAAU,GAAG,KAAK,oBAAoB;AAC/E,SAAO;AACT;AAEA,SAAS,WAAW,OAAgB,OAA0C;AAC5E,MACE,CAAC,MAAM,QAAQ,KAAK,KACpB,CAAC,MAAM,MAAM,CAAC,SAAS,OAAO,SAAS,YAAY,SAAS,QAAQ,CAAC,MAAM,QAAQ,IAAI,CAAC,GACxF;AACA,UAAM,IAAI,UAAU,GAAG,KAAK,+BAA+B;AAAA,EAC7D;AACA,SAAO;AACT;AAEA,SAAS,aAAa,OAAuB;AAC3C,QAAM,oBAAoB,IAAI,IAAI,sBAAsB;AACxD,MAAI,UAAU;AACd,aAAW,aAAa,OAAO;AAC7B,eAAW,kBAAkB,IAAI,SAAS,IAAI,KAAK,SAAS,KAAK;AAAA,EACnE;AACA,SAAO;AACT;AAEA,SAAS,oBAAoB,OAAgC,OAAuB;AAClF,QAAM,QAAQ,aAAa,KAAK;AAChC,SAAO,iBAAiB,8BAA8B,MAAM,cAAc,SACtE,IAAI,KAAK,2BAA2B,aAAa,MAAM,SAAS,CAAC,KACjE;AACN;AAEA,SAAS,QACP,QACA,QACmB;AACnB,QAAM,SAAS,oBAAI,IAAkB;AACrC,aAAW,SAAS,QAAQ;AAC1B,UAAM,MAAM,OAAO,KAAK;AACxB,UAAM,QAAQ,OAAO,IAAI,GAAG;AAC5B,QAAI,UAAU,OAAW,QAAO,IAAI,KAAK,CAAC,KAAK,CAAC;AAAA,QAC3C,OAAM,KAAK,KAAK;AAAA,EACvB;AACA,SAAO;AACT;","names":[]}
@@ -0,0 +1,8 @@
1
+ import {
2
+ exploreGraph
3
+ } from "./chunk-QY7IO247.js";
4
+ import "./chunk-EUZ5C6OC.js";
5
+ export {
6
+ exploreGraph
7
+ };
8
+ //# sourceMappingURL=explore-HRISJG7V.js.map
package/dist/index.d.ts CHANGED
@@ -268,18 +268,25 @@ type SeedRegistration = Readonly<{
268
268
  vectorIndex: Neo4jVectorIndex & Readonly<{
269
269
  property: string;
270
270
  }>;
271
+ vectorFilterProperties?: readonly string[] | undefined;
271
272
  fulltextIndex?: (Neo4jFulltextIndex & Readonly<{
272
273
  properties: readonly string[];
273
274
  }>) | undefined;
274
275
  entryRelationshipType?: string | undefined;
275
276
  }>;
276
277
  type GraphTransaction = Pick<ManagedTransaction, "run">;
278
+ declare const tenantScopeBrand: unique symbol;
279
+ type Neo4jTenantScope = Readonly<{
280
+ namespace: string;
281
+ [tenantScopeBrand]: true;
282
+ }>;
277
283
  declare abstract class Neo4jKnowledgeGraphBase<Schema extends Neo4jGraphSchema = Neo4jGraphSchema, Evidence extends Neo4jGraphEvidenceCapability = Neo4jGraphEvidenceCapability> {
278
284
  protected readonly owner: Neo4jClient;
279
285
  readonly schema: Schema;
286
+ readonly namespace?: string | undefined;
280
287
  abstract readonly seeds: Readonly<Record<string, SeedRegistration>>;
281
288
  abstract readonly evidenceCapability: Evidence;
282
- protected constructor(owner: Neo4jClient, schema: Schema);
289
+ protected constructor(owner: Neo4jClient, schema: Schema, namespace?: string | undefined);
283
290
  validate(options?: Neo4jGraphValidateOptions): Promise<void>;
284
291
  query(text: string, parameters: Record<string, unknown>, abortSignal?: AbortSignal, access?: "read" | "write"): Promise<QueryResult>;
285
292
  retrieve(options: GraphRetrieveOptions<Schema, Evidence>): Promise<GraphContext>;
@@ -298,8 +305,8 @@ declare class ManagedNeo4jKnowledgeGraph<Schema extends Neo4jGraphSchema> extend
298
305
  readonly evidenceCapability: "chunks";
299
306
  readonly seeds: Readonly<Record<string, SeedRegistration>>;
300
307
  readonly resources: ManagedNeo4jKnowledgeGraphOptions<Schema>["resources"];
301
- private readonly name;
302
- constructor(owner: Neo4jClient, options: ManagedNeo4jKnowledgeGraphOptions<Schema>);
308
+ readonly name: string;
309
+ constructor(owner: Neo4jClient, options: ManagedNeo4jKnowledgeGraphOptions<Schema>, tenantScope?: Neo4jTenantScope);
303
310
  ensure(options: Neo4jGraphEnsureOptions): Promise<void>;
304
311
  validate(options?: Neo4jGraphValidateOptions): Promise<void>;
305
312
  replaceDocuments(options: ReplaceNeo4jDocumentsOptions<Schema>): Promise<Neo4jGraphWriteResult>;
@@ -314,12 +321,20 @@ declare class Neo4jClient {
314
321
  readonly database: string | undefined;
315
322
  constructor(options: Neo4jClientOptions);
316
323
  managedKnowledgeGraph<Schema extends Neo4jGraphSchema>(options: ManagedNeo4jKnowledgeGraphOptions<Schema>): ManagedNeo4jKnowledgeGraph<Schema>;
324
+ tenant(tenantId: string): Neo4jTenant;
317
325
  knowledgeGraph<Schema extends Neo4jGraphSchema>(options: Neo4jKnowledgeGraphOptions<Schema>): Neo4jKnowledgeGraph<Schema>;
318
326
  nativeDriver(): Driver;
319
327
  close(): Promise<void>;
320
328
  [Symbol.asyncDispose](): Promise<void>;
321
329
  private assertOpen;
322
330
  }
331
+ declare class Neo4jTenant {
332
+ private readonly owner;
333
+ private readonly scope;
334
+ constructor(owner: Neo4jClient, scope: Neo4jTenantScope);
335
+ get namespace(): string;
336
+ managedKnowledgeGraph<Schema extends Neo4jGraphSchema>(options: ManagedNeo4jKnowledgeGraphOptions<Schema>): ManagedNeo4jKnowledgeGraph<Schema>;
337
+ }
323
338
 
324
339
  declare function exploreGraph<Schema extends Neo4jGraphSchema>(graph: Neo4jKnowledgeGraphBase<Schema>, options: GraphExploreOptions<Schema>): Promise<GraphExploreResult>;
325
340
 
@@ -329,4 +344,4 @@ declare function retrieveGraphContext<Schema extends Neo4jGraphSchema>(options:
329
344
 
330
345
  declare function defineNeo4jGraphSchema<const Options extends Neo4jGraphSchemaOptions>(options: Options): Neo4jGraphSchema<Options>;
331
346
 
332
- export { type DeleteNeo4jDocumentsOptions, type ExistingNeo4jSeed, type ExtractGraphFactsOptions, type ExtractGraphFactsResult, ManagedNeo4jKnowledgeGraph, type ManagedNeo4jKnowledgeGraphOptions, Neo4jClient, type Neo4jClientOptions, type Neo4jFulltextIndex, type Neo4jGraphChangeCounts, type Neo4jGraphChunk, type Neo4jGraphConflict, type Neo4jGraphContext, type Neo4jGraphContextNode, type Neo4jGraphContextRelationship, type Neo4jGraphContextSeed, type Neo4jGraphDocument, type Neo4jGraphEnsureOptions, type Neo4jGraphEntity, type Neo4jGraphEvidence, type Neo4jGraphEvidenceCapability, type Neo4jGraphEvidenceOptions, type Neo4jGraphFacts, type Neo4jGraphMention, type Neo4jGraphRelationship, type Neo4jGraphSchema, type Neo4jGraphSchemaOptions, type Neo4jGraphSearchOptions, type Neo4jGraphTraversalOptions, type Neo4jGraphValidateOptions, type Neo4jGraphWriteResult, type Neo4jHybridSearchOptions, Neo4jKnowledgeGraph, type Neo4jKnowledgeGraphOptions, type Neo4jNodeDefinition, type Neo4jNodeIdentity, type Neo4jOrphanEntityPolicy, type Neo4jProperties, type Neo4jPropertyPrimitive, type Neo4jPropertyValue, type Neo4jRelationshipDefinition, type Neo4jVectorIndex, type Neo4jVectorSearchOptions, type ReplaceNeo4jDocumentsOptions, type RetrieveGraphContextOptions, defineNeo4jGraphSchema, exploreGraph, extractGraphFacts, retrieveGraphContext };
347
+ export { type DeleteNeo4jDocumentsOptions, type ExistingNeo4jSeed, type ExtractGraphFactsOptions, type ExtractGraphFactsResult, ManagedNeo4jKnowledgeGraph, type ManagedNeo4jKnowledgeGraphOptions, Neo4jClient, type Neo4jClientOptions, type Neo4jFulltextIndex, type Neo4jGraphChangeCounts, type Neo4jGraphChunk, type Neo4jGraphConflict, type Neo4jGraphContext, type Neo4jGraphContextNode, type Neo4jGraphContextRelationship, type Neo4jGraphContextSeed, type Neo4jGraphDocument, type Neo4jGraphEnsureOptions, type Neo4jGraphEntity, type Neo4jGraphEvidence, type Neo4jGraphEvidenceCapability, type Neo4jGraphEvidenceOptions, type Neo4jGraphFacts, type Neo4jGraphMention, type Neo4jGraphRelationship, type Neo4jGraphSchema, type Neo4jGraphSchemaOptions, type Neo4jGraphSearchOptions, type Neo4jGraphTraversalOptions, type Neo4jGraphValidateOptions, type Neo4jGraphWriteResult, type Neo4jHybridSearchOptions, Neo4jKnowledgeGraph, type Neo4jKnowledgeGraphOptions, type Neo4jNodeDefinition, type Neo4jNodeIdentity, type Neo4jOrphanEntityPolicy, type Neo4jProperties, type Neo4jPropertyPrimitive, type Neo4jPropertyValue, type Neo4jRelationshipDefinition, Neo4jTenant, type Neo4jVectorIndex, type Neo4jVectorSearchOptions, type ReplaceNeo4jDocumentsOptions, type RetrieveGraphContextOptions, defineNeo4jGraphSchema, exploreGraph, extractGraphFacts, retrieveGraphContext };
package/dist/index.js CHANGED
@@ -1,16 +1,18 @@
1
1
  import {
2
2
  retrieveGraphContext
3
- } from "./chunk-YLW4LCKJ.js";
3
+ } from "./chunk-YCJZAWLH.js";
4
4
  import {
5
5
  exploreGraph
6
- } from "./chunk-PWE3ETSF.js";
6
+ } from "./chunk-QY7IO247.js";
7
7
  import {
8
8
  ManagedNeo4jKnowledgeGraph,
9
9
  Neo4jKnowledgeGraph,
10
- defineNeo4jGraphSchema
11
- } from "./chunk-QNHOT7P2.js";
10
+ defineNeo4jGraphSchema,
11
+ neo4jTenantScope
12
+ } from "./chunk-EUZ5C6OC.js";
12
13
 
13
14
  // src/client.ts
15
+ import { createHash } from "crypto";
14
16
  import { auth, driver as createDriver } from "neo4j-driver";
15
17
  var Neo4jClient = class {
16
18
  driver;
@@ -40,6 +42,10 @@ var Neo4jClient = class {
40
42
  this.assertOpen();
41
43
  return new ManagedNeo4jKnowledgeGraph(this, options);
42
44
  }
45
+ tenant(tenantId) {
46
+ this.assertOpen();
47
+ return new Neo4jTenant(this, neo4jTenantScope(tenantNamespace(tenantId)));
48
+ }
43
49
  knowledgeGraph(options) {
44
50
  this.assertOpen();
45
51
  return new Neo4jKnowledgeGraph(this, options);
@@ -60,6 +66,26 @@ var Neo4jClient = class {
60
66
  if (this.closed) throw new Error("Neo4jClient is closed.");
61
67
  }
62
68
  };
69
+ var Neo4jTenant = class {
70
+ constructor(owner, scope) {
71
+ this.owner = owner;
72
+ this.scope = scope;
73
+ }
74
+ owner;
75
+ scope;
76
+ get namespace() {
77
+ return this.scope.namespace;
78
+ }
79
+ managedKnowledgeGraph(options) {
80
+ this.owner.nativeDriver();
81
+ return new ManagedNeo4jKnowledgeGraph(this.owner, options, this.scope);
82
+ }
83
+ };
84
+ function tenantNamespace(tenantId) {
85
+ if (typeof tenantId !== "string" || tenantId.trim().length === 0)
86
+ throw new TypeError("Neo4j tenant id must be a non-empty string.");
87
+ return createHash("sha256").update(tenantId).digest("hex");
88
+ }
63
89
 
64
90
  // src/extract.ts
65
91
  import { extractGraphFacts as extractSharedGraphFacts, GraphFactConflictError } from "@anvia/graph";
@@ -71,6 +97,7 @@ export {
71
97
  ManagedNeo4jKnowledgeGraph,
72
98
  Neo4jClient,
73
99
  Neo4jKnowledgeGraph,
100
+ Neo4jTenant,
74
101
  defineNeo4jGraphSchema,
75
102
  exploreGraph,
76
103
  extractGraphFacts,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/client.ts","../src/extract.ts"],"sourcesContent":["import { auth, driver as createDriver, type Driver } from \"neo4j-driver\";\nimport { ManagedNeo4jKnowledgeGraph, Neo4jKnowledgeGraph } from \"./graph.js\";\nimport type {\n ManagedNeo4jKnowledgeGraphOptions,\n Neo4jClientOptions,\n Neo4jGraphSchema,\n Neo4jKnowledgeGraphOptions,\n} from \"./types.js\";\n\nexport class Neo4jClient {\n private readonly driver: Driver;\n private readonly ownsDriver: boolean;\n private closed = false;\n readonly database: string | undefined;\n\n constructor(options: Neo4jClientOptions) {\n this.database = options.database;\n if (\"driver\" in options) {\n this.driver = options.driver;\n this.ownsDriver = false;\n } else {\n if (typeof options.uri !== \"string\" || options.uri.length === 0) {\n throw new TypeError(\"Neo4jClient uri must be a non-empty string.\");\n }\n if (\n typeof options.auth.username !== \"string\" ||\n options.auth.username.length === 0 ||\n typeof options.auth.password !== \"string\"\n ) {\n throw new TypeError(\"Neo4jClient requires explicit username and password credentials.\");\n }\n this.driver = createDriver(\n options.uri,\n auth.basic(options.auth.username, options.auth.password),\n );\n this.ownsDriver = true;\n }\n }\n\n managedKnowledgeGraph<Schema extends Neo4jGraphSchema>(\n options: ManagedNeo4jKnowledgeGraphOptions<Schema>,\n ): ManagedNeo4jKnowledgeGraph<Schema> {\n this.assertOpen();\n return new ManagedNeo4jKnowledgeGraph(this, options);\n }\n\n knowledgeGraph<Schema extends Neo4jGraphSchema>(\n options: Neo4jKnowledgeGraphOptions<Schema>,\n ): Neo4jKnowledgeGraph<Schema> {\n this.assertOpen();\n return new Neo4jKnowledgeGraph(this, options);\n }\n\n nativeDriver(): Driver {\n this.assertOpen();\n return this.driver;\n }\n\n async close(): Promise<void> {\n if (this.closed) return;\n this.closed = true;\n if (this.ownsDriver) await this.driver.close();\n }\n\n [Symbol.asyncDispose](): Promise<void> {\n return this.close();\n }\n\n private assertOpen(): void {\n if (this.closed) throw new Error(\"Neo4jClient is closed.\");\n }\n}\n","import { extractGraphFacts as extractSharedGraphFacts, GraphFactConflictError } from \"@anvia/graph\";\nimport type {\n ExtractGraphFactsOptions,\n ExtractGraphFactsResult,\n Neo4jGraphSchema,\n} from \"./types.js\";\n\nexport { GraphFactConflictError };\n\nexport async function extractGraphFacts<\n Schema extends Neo4jGraphSchema,\n Model extends import(\"@anvia/core\").CompletionModel,\n>(options: ExtractGraphFactsOptions<Schema, Model>): Promise<ExtractGraphFactsResult<Schema>> {\n return extractSharedGraphFacts(options) as Promise<ExtractGraphFactsResult<Schema>>;\n}\n"],"mappings":";;;;;;;;;;;;;AAAA,SAAS,MAAM,UAAU,oBAAiC;AASnD,IAAM,cAAN,MAAkB;AAAA,EACN;AAAA,EACA;AAAA,EACT,SAAS;AAAA,EACR;AAAA,EAET,YAAY,SAA6B;AACvC,SAAK,WAAW,QAAQ;AACxB,QAAI,YAAY,SAAS;AACvB,WAAK,SAAS,QAAQ;AACtB,WAAK,aAAa;AAAA,IACpB,OAAO;AACL,UAAI,OAAO,QAAQ,QAAQ,YAAY,QAAQ,IAAI,WAAW,GAAG;AAC/D,cAAM,IAAI,UAAU,6CAA6C;AAAA,MACnE;AACA,UACE,OAAO,QAAQ,KAAK,aAAa,YACjC,QAAQ,KAAK,SAAS,WAAW,KACjC,OAAO,QAAQ,KAAK,aAAa,UACjC;AACA,cAAM,IAAI,UAAU,kEAAkE;AAAA,MACxF;AACA,WAAK,SAAS;AAAA,QACZ,QAAQ;AAAA,QACR,KAAK,MAAM,QAAQ,KAAK,UAAU,QAAQ,KAAK,QAAQ;AAAA,MACzD;AACA,WAAK,aAAa;AAAA,IACpB;AAAA,EACF;AAAA,EAEA,sBACE,SACoC;AACpC,SAAK,WAAW;AAChB,WAAO,IAAI,2BAA2B,MAAM,OAAO;AAAA,EACrD;AAAA,EAEA,eACE,SAC6B;AAC7B,SAAK,WAAW;AAChB,WAAO,IAAI,oBAAoB,MAAM,OAAO;AAAA,EAC9C;AAAA,EAEA,eAAuB;AACrB,SAAK,WAAW;AAChB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,MAAM,QAAuB;AAC3B,QAAI,KAAK,OAAQ;AACjB,SAAK,SAAS;AACd,QAAI,KAAK,WAAY,OAAM,KAAK,OAAO,MAAM;AAAA,EAC/C;AAAA,EAEA,CAAC,OAAO,YAAY,IAAmB;AACrC,WAAO,KAAK,MAAM;AAAA,EACpB;AAAA,EAEQ,aAAmB;AACzB,QAAI,KAAK,OAAQ,OAAM,IAAI,MAAM,wBAAwB;AAAA,EAC3D;AACF;;;ACvEA,SAAS,qBAAqB,yBAAyB,8BAA8B;AASrF,eAAsB,kBAGpB,SAA4F;AAC5F,SAAO,wBAAwB,OAAO;AACxC;","names":[]}
1
+ {"version":3,"sources":["../src/client.ts","../src/extract.ts"],"sourcesContent":["import { createHash } from \"node:crypto\";\nimport { auth, driver as createDriver, type Driver } from \"neo4j-driver\";\nimport {\n ManagedNeo4jKnowledgeGraph,\n neo4jTenantScope,\n Neo4jKnowledgeGraph,\n type Neo4jTenantScope,\n} from \"./graph.js\";\nimport type {\n ManagedNeo4jKnowledgeGraphOptions,\n Neo4jClientOptions,\n Neo4jGraphSchema,\n Neo4jKnowledgeGraphOptions,\n} from \"./types.js\";\n\nexport class Neo4jClient {\n private readonly driver: Driver;\n private readonly ownsDriver: boolean;\n private closed = false;\n readonly database: string | undefined;\n\n constructor(options: Neo4jClientOptions) {\n this.database = options.database;\n if (\"driver\" in options) {\n this.driver = options.driver;\n this.ownsDriver = false;\n } else {\n if (typeof options.uri !== \"string\" || options.uri.length === 0) {\n throw new TypeError(\"Neo4jClient uri must be a non-empty string.\");\n }\n if (\n typeof options.auth.username !== \"string\" ||\n options.auth.username.length === 0 ||\n typeof options.auth.password !== \"string\"\n ) {\n throw new TypeError(\"Neo4jClient requires explicit username and password credentials.\");\n }\n this.driver = createDriver(\n options.uri,\n auth.basic(options.auth.username, options.auth.password),\n );\n this.ownsDriver = true;\n }\n }\n\n managedKnowledgeGraph<Schema extends Neo4jGraphSchema>(\n options: ManagedNeo4jKnowledgeGraphOptions<Schema>,\n ): ManagedNeo4jKnowledgeGraph<Schema> {\n this.assertOpen();\n return new ManagedNeo4jKnowledgeGraph(this, options);\n }\n\n tenant(tenantId: string): Neo4jTenant {\n this.assertOpen();\n return new Neo4jTenant(this, neo4jTenantScope(tenantNamespace(tenantId)));\n }\n\n knowledgeGraph<Schema extends Neo4jGraphSchema>(\n options: Neo4jKnowledgeGraphOptions<Schema>,\n ): Neo4jKnowledgeGraph<Schema> {\n this.assertOpen();\n return new Neo4jKnowledgeGraph(this, options);\n }\n\n nativeDriver(): Driver {\n this.assertOpen();\n return this.driver;\n }\n\n async close(): Promise<void> {\n if (this.closed) return;\n this.closed = true;\n if (this.ownsDriver) await this.driver.close();\n }\n\n [Symbol.asyncDispose](): Promise<void> {\n return this.close();\n }\n\n private assertOpen(): void {\n if (this.closed) throw new Error(\"Neo4jClient is closed.\");\n }\n}\n\nexport class Neo4jTenant {\n constructor(\n private readonly owner: Neo4jClient,\n private readonly scope: Neo4jTenantScope,\n ) {}\n\n get namespace(): string {\n return this.scope.namespace;\n }\n\n managedKnowledgeGraph<Schema extends Neo4jGraphSchema>(\n options: ManagedNeo4jKnowledgeGraphOptions<Schema>,\n ): ManagedNeo4jKnowledgeGraph<Schema> {\n this.owner.nativeDriver();\n return new ManagedNeo4jKnowledgeGraph(this.owner, options, this.scope);\n }\n}\n\nfunction tenantNamespace(tenantId: string): string {\n if (typeof tenantId !== \"string\" || tenantId.trim().length === 0)\n throw new TypeError(\"Neo4j tenant id must be a non-empty string.\");\n return createHash(\"sha256\").update(tenantId).digest(\"hex\");\n}\n","import { extractGraphFacts as extractSharedGraphFacts, GraphFactConflictError } from \"@anvia/graph\";\nimport type {\n ExtractGraphFactsOptions,\n ExtractGraphFactsResult,\n Neo4jGraphSchema,\n} from \"./types.js\";\n\nexport { GraphFactConflictError };\n\nexport async function extractGraphFacts<\n Schema extends Neo4jGraphSchema,\n Model extends import(\"@anvia/core\").CompletionModel,\n>(options: ExtractGraphFactsOptions<Schema, Model>): Promise<ExtractGraphFactsResult<Schema>> {\n return extractSharedGraphFacts(options) as Promise<ExtractGraphFactsResult<Schema>>;\n}\n"],"mappings":";;;;;;;;;;;;;;AAAA,SAAS,kBAAkB;AAC3B,SAAS,MAAM,UAAU,oBAAiC;AAcnD,IAAM,cAAN,MAAkB;AAAA,EACN;AAAA,EACA;AAAA,EACT,SAAS;AAAA,EACR;AAAA,EAET,YAAY,SAA6B;AACvC,SAAK,WAAW,QAAQ;AACxB,QAAI,YAAY,SAAS;AACvB,WAAK,SAAS,QAAQ;AACtB,WAAK,aAAa;AAAA,IACpB,OAAO;AACL,UAAI,OAAO,QAAQ,QAAQ,YAAY,QAAQ,IAAI,WAAW,GAAG;AAC/D,cAAM,IAAI,UAAU,6CAA6C;AAAA,MACnE;AACA,UACE,OAAO,QAAQ,KAAK,aAAa,YACjC,QAAQ,KAAK,SAAS,WAAW,KACjC,OAAO,QAAQ,KAAK,aAAa,UACjC;AACA,cAAM,IAAI,UAAU,kEAAkE;AAAA,MACxF;AACA,WAAK,SAAS;AAAA,QACZ,QAAQ;AAAA,QACR,KAAK,MAAM,QAAQ,KAAK,UAAU,QAAQ,KAAK,QAAQ;AAAA,MACzD;AACA,WAAK,aAAa;AAAA,IACpB;AAAA,EACF;AAAA,EAEA,sBACE,SACoC;AACpC,SAAK,WAAW;AAChB,WAAO,IAAI,2BAA2B,MAAM,OAAO;AAAA,EACrD;AAAA,EAEA,OAAO,UAA+B;AACpC,SAAK,WAAW;AAChB,WAAO,IAAI,YAAY,MAAM,iBAAiB,gBAAgB,QAAQ,CAAC,CAAC;AAAA,EAC1E;AAAA,EAEA,eACE,SAC6B;AAC7B,SAAK,WAAW;AAChB,WAAO,IAAI,oBAAoB,MAAM,OAAO;AAAA,EAC9C;AAAA,EAEA,eAAuB;AACrB,SAAK,WAAW;AAChB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,MAAM,QAAuB;AAC3B,QAAI,KAAK,OAAQ;AACjB,SAAK,SAAS;AACd,QAAI,KAAK,WAAY,OAAM,KAAK,OAAO,MAAM;AAAA,EAC/C;AAAA,EAEA,CAAC,OAAO,YAAY,IAAmB;AACrC,WAAO,KAAK,MAAM;AAAA,EACpB;AAAA,EAEQ,aAAmB;AACzB,QAAI,KAAK,OAAQ,OAAM,IAAI,MAAM,wBAAwB;AAAA,EAC3D;AACF;AAEO,IAAM,cAAN,MAAkB;AAAA,EACvB,YACmB,OACA,OACjB;AAFiB;AACA;AAAA,EAChB;AAAA,EAFgB;AAAA,EACA;AAAA,EAGnB,IAAI,YAAoB;AACtB,WAAO,KAAK,MAAM;AAAA,EACpB;AAAA,EAEA,sBACE,SACoC;AACpC,SAAK,MAAM,aAAa;AACxB,WAAO,IAAI,2BAA2B,KAAK,OAAO,SAAS,KAAK,KAAK;AAAA,EACvE;AACF;AAEA,SAAS,gBAAgB,UAA0B;AACjD,MAAI,OAAO,aAAa,YAAY,SAAS,KAAK,EAAE,WAAW;AAC7D,UAAM,IAAI,UAAU,6CAA6C;AACnE,SAAO,WAAW,QAAQ,EAAE,OAAO,QAAQ,EAAE,OAAO,KAAK;AAC3D;;;AC1GA,SAAS,qBAAqB,yBAAyB,8BAA8B;AASrF,eAAsB,kBAGpB,SAA4F;AAC5F,SAAO,wBAAwB,OAAO;AACxC;","names":[]}
@@ -0,0 +1,8 @@
1
+ import {
2
+ retrieveGraphContext
3
+ } from "./chunk-YCJZAWLH.js";
4
+ import "./chunk-EUZ5C6OC.js";
5
+ export {
6
+ retrieveGraphContext
7
+ };
8
+ //# sourceMappingURL=retrieve-IJVPFOPP.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@anvia/neo4j",
3
- "version": "1.0.8",
3
+ "version": "1.0.10",
4
4
  "description": "Schema-first Neo4j GraphRAG integration for Anvia.",
5
5
  "author": "anvia",
6
6
  "maintainer": "Indra Zulfi",
@@ -28,17 +28,17 @@
28
28
  "dependencies": {
29
29
  "neo4j-driver": "^6.2.0",
30
30
  "zod": "^4.4.3",
31
- "@anvia/graph": "1.0.8"
31
+ "@anvia/graph": "1.0.10"
32
32
  },
33
33
  "devDependencies": {
34
34
  "@types/node": "^24.9.1",
35
35
  "tsup": "^8.5.0",
36
36
  "typescript": "^5.9.3",
37
37
  "vitest": "^4.0.8",
38
- "@anvia/core": "1.0.7"
38
+ "@anvia/core": "1.0.8"
39
39
  },
40
40
  "peerDependencies": {
41
- "@anvia/core": "1.0.7"
41
+ "@anvia/core": "1.0.8"
42
42
  },
43
43
  "scripts": {
44
44
  "build": "tsup src/index.ts --format esm --dts --sourcemap --clean",
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/explore.ts"],"sourcesContent":["import {\n resolveGraphExploreOptions,\n type GraphExploreNode,\n type GraphExploreOptions,\n type GraphExploreRelationship,\n type GraphExploreResult,\n type ResolvedGraphExploreExpandOptions,\n} from \"@anvia/graph\";\nimport { int, type Record as Neo4jRecord } from \"neo4j-driver\";\nimport { Neo4jKnowledgeGraphBase } from \"./graph.js\";\nimport { parseNeo4jProperties } from \"./schema.js\";\nimport type { Neo4jGraphSchema, Neo4jNodeIdentity } from \"./types.js\";\n\nexport async function exploreGraph<Schema extends Neo4jGraphSchema>(\n graph: Neo4jKnowledgeGraphBase<Schema>,\n options: GraphExploreOptions<Schema>,\n): Promise<GraphExploreResult> {\n if (!(graph instanceof Neo4jKnowledgeGraphBase)) {\n throw new TypeError(\"exploreGraph requires a Neo4j knowledge graph registration.\");\n }\n const resolved = resolveGraphExploreOptions(graph.schema, options);\n const records =\n resolved.mode === \"overview\"\n ? await overviewNodes(graph, resolved)\n : await expandedNodes(graph, resolved);\n const nodes = uniqueNodes(records.map((record) => nodeFromRecord(record, graph.schema)));\n const visibleNodes = nodes.slice(0, resolved.maxNodes);\n const relationships = await relationshipsBetween(\n graph,\n visibleNodes.map((node) => node.id),\n resolved.relationships,\n resolved.maxRelationships,\n resolved.abortSignal,\n );\n return {\n nodes: visibleNodes,\n relationships: relationships.slice(0, resolved.maxRelationships),\n truncated: {\n nodes: records.length > resolved.maxNodes || nodes.length > resolved.maxNodes,\n relationships: relationships.length > resolved.maxRelationships,\n },\n };\n}\n\nasync function overviewNodes(\n graph: Neo4jKnowledgeGraphBase,\n options: ReturnType<typeof resolveGraphExploreOptions> & { mode: \"overview\" },\n): Promise<readonly Neo4jRecord[]> {\n const result = await graph.query(\n `MATCH (node)\nWHERE any(type IN labels(node) WHERE type IN $nodeTypes)\nRETURN elementId(node) AS id, labels(node) AS labels, properties(node) AS properties\nORDER BY elementId(node)\nLIMIT $nodeLimit`,\n { nodeTypes: options.nodeTypes, nodeLimit: int(options.maxNodes + 1) },\n options.abortSignal,\n );\n return result.records;\n}\n\nasync function expandedNodes(\n graph: Neo4jKnowledgeGraphBase,\n options: ResolvedGraphExploreExpandOptions,\n): Promise<readonly Neo4jRecord[]> {\n const roots = await graph.query(\n `MATCH (node)\nWHERE elementId(node) IN $nodeIds\n AND any(type IN labels(node) WHERE type IN $nodeTypes)\nRETURN elementId(node) AS id, labels(node) AS labels, properties(node) AS properties`,\n { nodeIds: options.nodeIds, nodeTypes: options.nodeTypes },\n options.abortSignal,\n );\n if (options.relationships.length === 0) return roots.records;\n const remainingNodeLimit = options.maxNodes + 1 - roots.records.length;\n if (remainingNodeLimit <= 0) return roots.records;\n const pattern = traversalPattern(options.direction, options.maxDepth);\n const neighbors = await graph.query(\n `MATCH (root) WHERE elementId(root) IN $nodeIds\nMATCH path = ${pattern}\nWHERE all(rel IN relationships(path) WHERE type(rel) IN $relationshipTypes)\n AND any(type IN labels(node) WHERE type IN $nodeTypes)\nRETURN elementId(node) AS id, labels(node) AS labels, properties(node) AS properties\nLIMIT $nodeLimit`,\n {\n nodeIds: options.nodeIds,\n nodeTypes: options.nodeTypes,\n relationshipTypes: options.relationships,\n nodeLimit: int(remainingNodeLimit),\n },\n options.abortSignal,\n );\n return [...roots.records, ...neighbors.records];\n}\n\nasync function relationshipsBetween(\n graph: Neo4jKnowledgeGraphBase,\n nodeIds: readonly string[],\n relationshipTypes: readonly string[],\n maxRelationships: number,\n abortSignal?: AbortSignal,\n): Promise<GraphExploreRelationship[]> {\n if (nodeIds.length === 0 || relationshipTypes.length === 0) return [];\n const result = await graph.query(\n `MATCH (from)-[relationship]->(to)\nWHERE elementId(from) IN $nodeIds\n AND elementId(to) IN $nodeIds\n AND type(relationship) IN $relationshipTypes\nRETURN elementId(relationship) AS id,\n type(relationship) AS type,\n elementId(from) AS source,\n elementId(to) AS target,\n properties(relationship) AS properties\nORDER BY elementId(relationship)\nLIMIT $relationshipLimit`,\n {\n nodeIds,\n relationshipTypes,\n relationshipLimit: int(maxRelationships + 1),\n },\n abortSignal,\n );\n return result.records.map(relationshipFromRecord);\n}\n\nfunction nodeFromRecord(record: Neo4jRecord, schema: Neo4jGraphSchema): GraphExploreNode {\n const id = stringValue(record.get(\"id\"), \"Neo4j explorer node id\");\n const labels = stringArray(record.get(\"labels\"), \"Neo4j explorer node labels\");\n const raw = objectValue(record.get(\"properties\"), \"Neo4j explorer node properties\");\n const type = labels.find((label) => label in schema.nodes);\n if (type === undefined) throw new TypeError(\"Neo4j explorer node has no registered type.\");\n const properties = applicationProperties(raw, \"Neo4j explorer node properties\");\n const node: {\n id: string;\n key?: string | undefined;\n type: string;\n identity: Neo4jNodeIdentity;\n properties: typeof properties;\n } = {\n id,\n type,\n identity: identityProperties(schema, type, properties),\n properties,\n };\n const key = raw.__anvia_key;\n if (typeof key === \"string\") node.key = key;\n return node;\n}\n\nfunction relationshipFromRecord(record: Neo4jRecord): GraphExploreRelationship {\n const raw = objectValue(record.get(\"properties\"), \"Neo4j explorer relationship properties\");\n const relationship: {\n id: string;\n key?: string | undefined;\n type: string;\n from: string;\n to: string;\n properties: ReturnType<typeof applicationProperties>;\n } = {\n id: stringValue(record.get(\"id\"), \"Neo4j explorer relationship id\"),\n type: stringValue(record.get(\"type\"), \"Neo4j explorer relationship type\"),\n from: stringValue(record.get(\"source\"), \"Neo4j explorer relationship source\"),\n to: stringValue(record.get(\"target\"), \"Neo4j explorer relationship target\"),\n properties: applicationProperties(raw, \"Neo4j explorer relationship properties\"),\n };\n const key = raw.__anvia_key;\n if (typeof key === \"string\") relationship.key = key;\n return relationship;\n}\n\nfunction identityProperties(\n schema: Neo4jGraphSchema,\n type: string,\n properties: ReturnType<typeof applicationProperties>,\n): Neo4jNodeIdentity {\n const identity: Record<string, string | number | boolean> = {};\n const definition = schema.nodes[type];\n if (definition === undefined) return identity;\n for (const property of definition.identity) {\n const value = properties[property];\n if (typeof value === \"string\" || typeof value === \"number\" || typeof value === \"boolean\") {\n identity[property] = value;\n }\n }\n return identity;\n}\n\nfunction applicationProperties(value: Record<string, unknown>, label: string) {\n return parseNeo4jProperties(\n Object.fromEntries(Object.entries(value).filter(([key]) => !key.startsWith(\"__anvia_\"))),\n label,\n );\n}\n\nfunction uniqueNodes(nodes: readonly GraphExploreNode[]): GraphExploreNode[] {\n return [...new Map(nodes.map((node) => [node.id, node])).values()];\n}\n\nfunction traversalPattern(direction: \"outgoing\" | \"incoming\" | \"both\", maxDepth: number): string {\n if (direction === \"outgoing\") return `(root)-[*1..${maxDepth}]->(node)`;\n if (direction === \"incoming\") return `(root)<-[*1..${maxDepth}]-(node)`;\n return `(root)-[*1..${maxDepth}]-(node)`;\n}\n\nfunction stringValue(value: unknown, label: string): string {\n if (typeof value !== \"string\") throw new TypeError(`${label} must be a string.`);\n return value;\n}\n\nfunction stringArray(value: unknown, label: string): string[] {\n if (!Array.isArray(value) || !value.every((item) => typeof item === \"string\")) {\n throw new TypeError(`${label} must be a string array.`);\n }\n return value;\n}\n\nfunction objectValue(value: unknown, label: string): Record<string, unknown> {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n throw new TypeError(`${label} must be an object.`);\n }\n return value as Record<string, unknown>;\n}\n"],"mappings":"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","names":[]}