🚀 Socket Launch Week Day 5:Introducing Repository Access Permissions and Custom Roles.Learn more
Sign In

@inferagraph/gremlin

Package Overview
Dependencies
Maintainers
1
Versions
5
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@inferagraph/gremlin - npm Package Compare versions

Comparing version
0.2.0
to
0.2.1
+2
-2
dist/index.cjs

@@ -39,6 +39,6 @@ "use strict";

// src/GremlinDataSource.ts
var import_core = require("@inferagraph/core");
var import_data = require("@inferagraph/core/data");
var import_gremlin = __toESM(require("gremlin"), 1);
var { driver } = import_gremlin.default;
var GremlinDataSource = class extends import_core.DataSource {
var GremlinDataSource = class extends import_data.DataSource {
name = "gremlin";

@@ -45,0 +45,0 @@ client = null;

@@ -1,1 +0,1 @@

{"version":3,"sources":["../src/index.ts","../src/GremlinDataSource.ts","../src/factory.ts"],"sourcesContent":["export { GremlinDataSource } from './GremlinDataSource.js';\nexport { gremlinDataSource } from './factory.js';\nexport type { GremlinDataSourceConfig, GremlinVertex } from './types.js';\n","import { DataSource } from '@inferagraph/core';\nimport type {\n DataAdapterConfig, GraphData, NodeId, NodeData, EdgeData,\n ContentData, PaginationOptions, PaginatedResult, DataFilter,\n} from '@inferagraph/core';\nimport gremlin from 'gremlin';\nimport type { GremlinDataSourceConfig, GremlinVertex } from './types.js';\n\nconst { driver } = gremlin;\n\nexport class GremlinDataSource extends DataSource {\n readonly name = 'gremlin';\n private client: InstanceType<typeof driver.Client> | null = null;\n private config: GremlinDataSourceConfig;\n private nameProperty: string;\n\n constructor(config: GremlinDataSourceConfig) {\n super();\n this.config = config;\n this.nameProperty = config.nameProperty ?? 'name';\n }\n\n async connect(): Promise<void> {\n const authenticator = this.config.key\n ? new driver.auth.PlainTextSaslAuthenticator(\n `/dbs/${this.config.database}/colls/${this.config.container}`,\n this.config.key,\n )\n : undefined;\n\n this.client = new driver.Client(this.config.endpoint, {\n authenticator,\n traversalsource: 'g',\n rejectUnauthorized: true,\n mimeType: 'application/vnd.gremlin-v2.0+json',\n });\n\n await this.client.open();\n }\n\n async disconnect(): Promise<void> {\n if (this.client) {\n await this.client.close();\n this.client = null;\n }\n }\n\n isConnected(): boolean {\n return this.client !== null;\n }\n\n async getInitialView(config?: DataAdapterConfig): Promise<GraphData> {\n this.ensureConnected();\n const limit = (config?.limit as number) ?? 100;\n\n // Get vertices\n const vertexResult = await this.client!.submit(`g.V().limit(${limit})`);\n const nodes = this.transformVertices(vertexResult._items || []);\n\n // Get edges between those vertices\n const nodeIds = nodes.map(n => n.id);\n if (nodeIds.length === 0) return { nodes: [], edges: [] };\n\n const edges = await this.fetchEdgesAmongNodes(nodeIds);\n return { nodes, edges };\n }\n\n async getNode(id: NodeId): Promise<NodeData | undefined> {\n this.ensureConnected();\n const result = await this.client!.submit(`g.V(${this.formatKey(this.resolveKey(id))})`);\n const items = result._items || [];\n if (items.length === 0) return undefined;\n return this.transformVertices(items)[0];\n }\n\n async getNeighbors(nodeId: NodeId, depth: number = 1): Promise<GraphData> {\n this.ensureConnected();\n\n const inlinedKey = this.formatKey(this.resolveKey(nodeId));\n\n // Get neighbors up to depth\n const vertexResult = await this.client!.submit(\n `g.V(${inlinedKey}).repeat(both().simplePath()).times(depth).dedup()`,\n { depth },\n );\n const neighborNodes = this.transformVertices(vertexResult._items || []);\n\n // Also get the origin node\n const originResult = await this.client!.submit(`g.V(${inlinedKey})`);\n const originNodes = this.transformVertices(originResult._items || []);\n\n const allNodes = [...originNodes, ...neighborNodes];\n const allNodeIds = allNodes.map(n => n.id);\n\n const edges = await this.fetchEdgesAmongNodes(allNodeIds);\n return { nodes: allNodes, edges };\n }\n\n async findPath(fromId: NodeId, toId: NodeId): Promise<GraphData> {\n this.ensureConnected();\n\n // Termination uses `has(T.id, toId)` rather than `hasId(toId)`. The\n // canonical T.id token compares the document id on Cosmos and the\n // vertex id on TinkerPop, and unlike `hasId()` it accepts a plain\n // id (NOT a composite-key tuple) — which is what we want here, since\n // the bound `toId` is the raw vertex id, not the partition pair.\n //\n // `fromId` is inlined as a Gremlin literal because Cosmos parameter\n // bindings reject lists of tuples; see formatKey().\n const inlinedFrom = this.formatKey(this.resolveKey(fromId));\n const result = await this.client!.submit(\n `g.V(${inlinedFrom}).repeat(both().simplePath()).until(has(T.id, toId)).limit(1).path()`,\n { toId },\n );\n\n const items = result._items || [];\n if (items.length === 0) return { nodes: [], edges: [] };\n\n // Extract path objects\n const pathObjects = items[0]?.objects || [];\n const nodes: NodeData[] = [];\n\n for (const obj of pathObjects) {\n if (obj.id && obj.label && !obj.inV) {\n nodes.push(this.transformVertex(obj));\n }\n }\n\n // Get edges between path nodes\n const nodeIds = nodes.map(n => n.id);\n const pathEdges = await this.fetchEdgesAmongNodes(nodeIds);\n return { nodes, edges: pathEdges };\n }\n\n async search(query: string, pagination?: PaginationOptions): Promise<PaginatedResult<NodeData>> {\n this.ensureConnected();\n\n const result = await this.client!.submit(\n `g.V().has('${this.nameProperty}', TextP.containing(query))`,\n { query },\n );\n\n const allItems = this.transformVertices(result._items || []);\n return this.paginate(allItems, pagination);\n }\n\n async filter(filter: DataFilter, pagination?: PaginationOptions): Promise<PaginatedResult<NodeData>> {\n this.ensureConnected();\n\n // Build Gremlin traversal dynamically\n let traversal = 'g.V()';\n const bindings: Record<string, unknown> = {};\n\n if (filter.types?.length) {\n traversal += `.has('type', within(types))`;\n bindings.types = filter.types;\n }\n if (filter.search) {\n traversal += `.has('${this.nameProperty}', TextP.containing(searchText))`;\n bindings.searchText = filter.search;\n }\n if (filter.attributes) {\n let i = 0;\n for (const [key, value] of Object.entries(filter.attributes)) {\n traversal += `.has(attrKey${i}, attrVal${i})`;\n bindings[`attrKey${i}`] = key;\n bindings[`attrVal${i}`] = value;\n i++;\n }\n }\n\n const result = await this.client!.submit(traversal, bindings);\n const allItems = this.transformVertices(result._items || []);\n return this.paginate(allItems, pagination);\n }\n\n async getContent(nodeId: NodeId): Promise<ContentData | undefined> {\n this.ensureConnected();\n\n const inlinedKey = this.formatKey(this.resolveKey(nodeId));\n const result = await this.client!.submit(\n `g.V(${inlinedKey}).has('content')`,\n );\n\n const items = result._items || [];\n if (items.length === 0) return undefined;\n\n const vertex = items[0];\n const content = this.getProperty(vertex, 'content');\n if (!content) return undefined;\n\n return {\n nodeId,\n content: String(content),\n contentType: (this.getProperty(vertex, 'contentType') as string) ?? 'text',\n };\n }\n\n // --- Private Helpers ---\n\n private ensureConnected(): void {\n if (!this.client) {\n throw new Error('GremlinDataSource is not connected. Call connect() first.');\n }\n }\n\n /**\n * Resolve a vertex id into the value passed to g.V(...).\n * Default: identity (TinkerPop / unpartitioned).\n * If `getCompositeKey` is configured (e.g. for Cosmos DB partitioned\n * containers), delegates to that callback.\n */\n private resolveKey(id: string): string | [string, string] {\n return this.config.getCompositeKey?.(id) ?? id;\n }\n\n /**\n * Format a resolved key as a Gremlin literal to inline into the query.\n *\n * Why inline rather than bind? Cosmos DB Gremlin parameter bindings only\n * accept scalars or arrays of scalars — bindings can NOT carry tuples\n * (`[pk, id]`) nor arrays of tuples. When `getCompositeKey` returns a\n * tuple, the only portable option is to inline the value into the query\n * string. We always inline (even for the scalar case) for consistency.\n *\n * String escaping: Gremlin string literals use single quotes. The\n * untrusted-input risk is small (ids come from host code) but the library\n * defends anyway: backslashes become `\\\\` and single quotes become `\\'`.\n */\n private formatKey(key: string | [string, string]): string {\n if (Array.isArray(key)) {\n return `[${this.escapeString(key[0])}, ${this.escapeString(key[1])}]`;\n }\n return this.escapeString(key);\n }\n\n private escapeString(value: string): string {\n return `'${value.replace(/\\\\/g, '\\\\\\\\').replace(/'/g, \"\\\\'\")}'`;\n }\n\n /**\n * Fetch edges among a known set of vertices.\n *\n * The traversal is `g.V(<inlined keys>).bothE().dedup()` — composite-key\n * safe (each key may be a tuple, inlined directly into the query) and\n * avoids `within(<list-of-tuples>)`, which is unreliable on Cosmos DB\n * Gremlin. We then drop edges with an endpoint outside the `nodeIds`\n * set client-side, since `bothE()` includes edges to neighbors we did\n * not request.\n */\n private async fetchEdgesAmongNodes(nodeIds: string[]): Promise<EdgeData[]> {\n const inlinedKeys = nodeIds\n .map(nid => this.formatKey(this.resolveKey(nid)))\n .join(', ');\n const result = await this.client!.submit(\n `g.V(${inlinedKeys}).bothE().dedup()`,\n );\n const allEdges = this.transformEdges(result._items || []);\n const idSet = new Set(nodeIds);\n return allEdges.filter(e => idSet.has(e.sourceId) && idSet.has(e.targetId));\n }\n\n private transformVertices(items: unknown[]): NodeData[] {\n return items.map(item => this.transformVertex(item));\n }\n\n private transformVertex(vertex: unknown): NodeData {\n const v = vertex as Record<string, unknown>;\n const id = String(v.id);\n const attributes: Record<string, unknown> = {};\n\n // Resolve the semantic type of the vertex. Default = Gremlin label\n // (TinkerPop convention). Hosts whose data stores a constant label\n // and the real type in a property (e.g. Bible Graph: every vertex\n // labeled 'Unit', actual type on a `type` property) override via\n // `getType` to surface the right value. If getType returns undefined,\n // fall back to the label.\n const resolvedType = this.config.getType?.(v as unknown as GremlinVertex) ?? (v.label as string | undefined);\n if (resolvedType !== undefined) attributes.type = resolvedType;\n\n // Gremlin properties can be nested objects\n const properties = v.properties as Record<string, unknown> | undefined;\n if (properties) {\n for (const [key, val] of Object.entries(properties)) {\n if (Array.isArray(val)) {\n // Multi-value property\n attributes[key] = val.length === 1\n ? (val[0] as Record<string, unknown>)?.value ?? val[0]\n : val.map((item: unknown) => (item as Record<string, unknown>)?.value ?? item);\n } else if (typeof val === 'object' && val !== null && 'value' in (val as Record<string, unknown>)) {\n attributes[key] = (val as Record<string, unknown>).value;\n } else {\n attributes[key] = val;\n }\n }\n }\n\n return { id, attributes };\n }\n\n private transformEdges(items: unknown[]): EdgeData[] {\n return items.map((edge: unknown) => {\n const e = edge as Record<string, unknown>;\n const outV = e.outV as Record<string, unknown> | string | undefined;\n const inV = e.inV as Record<string, unknown> | string | undefined;\n return {\n id: String(e.id),\n sourceId: String(typeof outV === 'object' && outV !== null ? outV.id : outV),\n targetId: String(typeof inV === 'object' && inV !== null ? inV.id : inV),\n attributes: {\n type: (e.label as string) ?? '',\n ...((e.properties as Record<string, unknown>) || {}),\n },\n };\n });\n }\n\n private getProperty(vertex: unknown, key: string): unknown {\n const v = vertex as Record<string, unknown>;\n const properties = v.properties as Record<string, unknown> | undefined;\n if (properties?.[key]) {\n const prop = properties[key];\n if (Array.isArray(prop)) return (prop[0] as Record<string, unknown>)?.value ?? prop[0];\n if (typeof prop === 'object' && prop !== null && 'value' in (prop as Record<string, unknown>)) return (prop as Record<string, unknown>).value;\n return prop;\n }\n return undefined;\n }\n\n private paginate(items: NodeData[], pagination?: PaginationOptions): PaginatedResult<NodeData> {\n const total = items.length;\n if (!pagination) return { items, total, hasMore: false };\n const { offset, limit } = pagination;\n const sliced = items.slice(offset, offset + limit);\n return { items: sliced, total, hasMore: offset + limit < total };\n }\n}\n","import { GremlinDataSource } from './GremlinDataSource.js';\nimport type { GremlinDataSourceConfig } from './types.js';\n\n/**\n * Factory function that returns a configured `GremlinDataSource`. This is\n * the recommended on-ramp — the package internalizes Gremlin SDK\n * construction (storage owns SDK setup), so callers only supply domain\n * config (endpoint, auth, partition resolver, etc.).\n *\n * Direct `new GremlinDataSource(config)` construction is the escape hatch\n * for subclasses or callers that want to bypass the factory.\n */\nexport function gremlinDataSource(\n config: GremlinDataSourceConfig,\n): GremlinDataSource {\n return new GremlinDataSource(config);\n}\n"],"mappings":"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","names":["gremlin"]}
{"version":3,"sources":["../src/index.ts","../src/GremlinDataSource.ts","../src/factory.ts"],"sourcesContent":["export { GremlinDataSource } from './GremlinDataSource.js';\nexport { gremlinDataSource } from './factory.js';\nexport type { GremlinDataSourceConfig, GremlinVertex } from './types.js';\n","import { DataSource } from '@inferagraph/core/data';\nimport type {\n DataAdapterConfig, GraphData, NodeId, NodeData, EdgeData,\n ContentData, PaginationOptions, PaginatedResult, DataFilter,\n} from '@inferagraph/core/data';\nimport gremlin from 'gremlin';\nimport type { GremlinDataSourceConfig, GremlinVertex } from './types.js';\n\nconst { driver } = gremlin;\n\nexport class GremlinDataSource extends DataSource {\n readonly name = 'gremlin';\n private client: InstanceType<typeof driver.Client> | null = null;\n private config: GremlinDataSourceConfig;\n private nameProperty: string;\n\n constructor(config: GremlinDataSourceConfig) {\n super();\n this.config = config;\n this.nameProperty = config.nameProperty ?? 'name';\n }\n\n async connect(): Promise<void> {\n const authenticator = this.config.key\n ? new driver.auth.PlainTextSaslAuthenticator(\n `/dbs/${this.config.database}/colls/${this.config.container}`,\n this.config.key,\n )\n : undefined;\n\n this.client = new driver.Client(this.config.endpoint, {\n authenticator,\n traversalsource: 'g',\n rejectUnauthorized: true,\n mimeType: 'application/vnd.gremlin-v2.0+json',\n });\n\n await this.client.open();\n }\n\n async disconnect(): Promise<void> {\n if (this.client) {\n await this.client.close();\n this.client = null;\n }\n }\n\n isConnected(): boolean {\n return this.client !== null;\n }\n\n async getInitialView(config?: DataAdapterConfig): Promise<GraphData> {\n this.ensureConnected();\n const limit = (config?.limit as number) ?? 100;\n\n // Get vertices\n const vertexResult = await this.client!.submit(`g.V().limit(${limit})`);\n const nodes = this.transformVertices(vertexResult._items || []);\n\n // Get edges between those vertices\n const nodeIds = nodes.map(n => n.id);\n if (nodeIds.length === 0) return { nodes: [], edges: [] };\n\n const edges = await this.fetchEdgesAmongNodes(nodeIds);\n return { nodes, edges };\n }\n\n async getNode(id: NodeId): Promise<NodeData | undefined> {\n this.ensureConnected();\n const result = await this.client!.submit(`g.V(${this.formatKey(this.resolveKey(id))})`);\n const items = result._items || [];\n if (items.length === 0) return undefined;\n return this.transformVertices(items)[0];\n }\n\n async getNeighbors(nodeId: NodeId, depth: number = 1): Promise<GraphData> {\n this.ensureConnected();\n\n const inlinedKey = this.formatKey(this.resolveKey(nodeId));\n\n // Get neighbors up to depth\n const vertexResult = await this.client!.submit(\n `g.V(${inlinedKey}).repeat(both().simplePath()).times(depth).dedup()`,\n { depth },\n );\n const neighborNodes = this.transformVertices(vertexResult._items || []);\n\n // Also get the origin node\n const originResult = await this.client!.submit(`g.V(${inlinedKey})`);\n const originNodes = this.transformVertices(originResult._items || []);\n\n const allNodes = [...originNodes, ...neighborNodes];\n const allNodeIds = allNodes.map(n => n.id);\n\n const edges = await this.fetchEdgesAmongNodes(allNodeIds);\n return { nodes: allNodes, edges };\n }\n\n async findPath(fromId: NodeId, toId: NodeId): Promise<GraphData> {\n this.ensureConnected();\n\n // Termination uses `has(T.id, toId)` rather than `hasId(toId)`. The\n // canonical T.id token compares the document id on Cosmos and the\n // vertex id on TinkerPop, and unlike `hasId()` it accepts a plain\n // id (NOT a composite-key tuple) — which is what we want here, since\n // the bound `toId` is the raw vertex id, not the partition pair.\n //\n // `fromId` is inlined as a Gremlin literal because Cosmos parameter\n // bindings reject lists of tuples; see formatKey().\n const inlinedFrom = this.formatKey(this.resolveKey(fromId));\n const result = await this.client!.submit(\n `g.V(${inlinedFrom}).repeat(both().simplePath()).until(has(T.id, toId)).limit(1).path()`,\n { toId },\n );\n\n const items = result._items || [];\n if (items.length === 0) return { nodes: [], edges: [] };\n\n // Extract path objects\n const pathObjects = items[0]?.objects || [];\n const nodes: NodeData[] = [];\n\n for (const obj of pathObjects) {\n if (obj.id && obj.label && !obj.inV) {\n nodes.push(this.transformVertex(obj));\n }\n }\n\n // Get edges between path nodes\n const nodeIds = nodes.map(n => n.id);\n const pathEdges = await this.fetchEdgesAmongNodes(nodeIds);\n return { nodes, edges: pathEdges };\n }\n\n async search(query: string, pagination?: PaginationOptions): Promise<PaginatedResult<NodeData>> {\n this.ensureConnected();\n\n const result = await this.client!.submit(\n `g.V().has('${this.nameProperty}', TextP.containing(query))`,\n { query },\n );\n\n const allItems = this.transformVertices(result._items || []);\n return this.paginate(allItems, pagination);\n }\n\n async filter(filter: DataFilter, pagination?: PaginationOptions): Promise<PaginatedResult<NodeData>> {\n this.ensureConnected();\n\n // Build Gremlin traversal dynamically\n let traversal = 'g.V()';\n const bindings: Record<string, unknown> = {};\n\n if (filter.types?.length) {\n traversal += `.has('type', within(types))`;\n bindings.types = filter.types;\n }\n if (filter.search) {\n traversal += `.has('${this.nameProperty}', TextP.containing(searchText))`;\n bindings.searchText = filter.search;\n }\n if (filter.attributes) {\n let i = 0;\n for (const [key, value] of Object.entries(filter.attributes)) {\n traversal += `.has(attrKey${i}, attrVal${i})`;\n bindings[`attrKey${i}`] = key;\n bindings[`attrVal${i}`] = value;\n i++;\n }\n }\n\n const result = await this.client!.submit(traversal, bindings);\n const allItems = this.transformVertices(result._items || []);\n return this.paginate(allItems, pagination);\n }\n\n async getContent(nodeId: NodeId): Promise<ContentData | undefined> {\n this.ensureConnected();\n\n const inlinedKey = this.formatKey(this.resolveKey(nodeId));\n const result = await this.client!.submit(\n `g.V(${inlinedKey}).has('content')`,\n );\n\n const items = result._items || [];\n if (items.length === 0) return undefined;\n\n const vertex = items[0];\n const content = this.getProperty(vertex, 'content');\n if (!content) return undefined;\n\n return {\n nodeId,\n content: String(content),\n contentType: (this.getProperty(vertex, 'contentType') as string) ?? 'text',\n };\n }\n\n // --- Private Helpers ---\n\n private ensureConnected(): void {\n if (!this.client) {\n throw new Error('GremlinDataSource is not connected. Call connect() first.');\n }\n }\n\n /**\n * Resolve a vertex id into the value passed to g.V(...).\n * Default: identity (TinkerPop / unpartitioned).\n * If `getCompositeKey` is configured (e.g. for Cosmos DB partitioned\n * containers), delegates to that callback.\n */\n private resolveKey(id: string): string | [string, string] {\n return this.config.getCompositeKey?.(id) ?? id;\n }\n\n /**\n * Format a resolved key as a Gremlin literal to inline into the query.\n *\n * Why inline rather than bind? Cosmos DB Gremlin parameter bindings only\n * accept scalars or arrays of scalars — bindings can NOT carry tuples\n * (`[pk, id]`) nor arrays of tuples. When `getCompositeKey` returns a\n * tuple, the only portable option is to inline the value into the query\n * string. We always inline (even for the scalar case) for consistency.\n *\n * String escaping: Gremlin string literals use single quotes. The\n * untrusted-input risk is small (ids come from host code) but the library\n * defends anyway: backslashes become `\\\\` and single quotes become `\\'`.\n */\n private formatKey(key: string | [string, string]): string {\n if (Array.isArray(key)) {\n return `[${this.escapeString(key[0])}, ${this.escapeString(key[1])}]`;\n }\n return this.escapeString(key);\n }\n\n private escapeString(value: string): string {\n return `'${value.replace(/\\\\/g, '\\\\\\\\').replace(/'/g, \"\\\\'\")}'`;\n }\n\n /**\n * Fetch edges among a known set of vertices.\n *\n * The traversal is `g.V(<inlined keys>).bothE().dedup()` — composite-key\n * safe (each key may be a tuple, inlined directly into the query) and\n * avoids `within(<list-of-tuples>)`, which is unreliable on Cosmos DB\n * Gremlin. We then drop edges with an endpoint outside the `nodeIds`\n * set client-side, since `bothE()` includes edges to neighbors we did\n * not request.\n */\n private async fetchEdgesAmongNodes(nodeIds: string[]): Promise<EdgeData[]> {\n const inlinedKeys = nodeIds\n .map(nid => this.formatKey(this.resolveKey(nid)))\n .join(', ');\n const result = await this.client!.submit(\n `g.V(${inlinedKeys}).bothE().dedup()`,\n );\n const allEdges = this.transformEdges(result._items || []);\n const idSet = new Set(nodeIds);\n return allEdges.filter(e => idSet.has(e.sourceId) && idSet.has(e.targetId));\n }\n\n private transformVertices(items: unknown[]): NodeData[] {\n return items.map(item => this.transformVertex(item));\n }\n\n private transformVertex(vertex: unknown): NodeData {\n const v = vertex as Record<string, unknown>;\n const id = String(v.id);\n const attributes: Record<string, unknown> = {};\n\n // Resolve the semantic type of the vertex. Default = Gremlin label\n // (TinkerPop convention). Hosts whose data stores a constant label\n // and the real type in a property (e.g. Bible Graph: every vertex\n // labeled 'Unit', actual type on a `type` property) override via\n // `getType` to surface the right value. If getType returns undefined,\n // fall back to the label.\n const resolvedType = this.config.getType?.(v as unknown as GremlinVertex) ?? (v.label as string | undefined);\n if (resolvedType !== undefined) attributes.type = resolvedType;\n\n // Gremlin properties can be nested objects\n const properties = v.properties as Record<string, unknown> | undefined;\n if (properties) {\n for (const [key, val] of Object.entries(properties)) {\n if (Array.isArray(val)) {\n // Multi-value property\n attributes[key] = val.length === 1\n ? (val[0] as Record<string, unknown>)?.value ?? val[0]\n : val.map((item: unknown) => (item as Record<string, unknown>)?.value ?? item);\n } else if (typeof val === 'object' && val !== null && 'value' in (val as Record<string, unknown>)) {\n attributes[key] = (val as Record<string, unknown>).value;\n } else {\n attributes[key] = val;\n }\n }\n }\n\n return { id, attributes };\n }\n\n private transformEdges(items: unknown[]): EdgeData[] {\n return items.map((edge: unknown) => {\n const e = edge as Record<string, unknown>;\n const outV = e.outV as Record<string, unknown> | string | undefined;\n const inV = e.inV as Record<string, unknown> | string | undefined;\n return {\n id: String(e.id),\n sourceId: String(typeof outV === 'object' && outV !== null ? outV.id : outV),\n targetId: String(typeof inV === 'object' && inV !== null ? inV.id : inV),\n attributes: {\n type: (e.label as string) ?? '',\n ...((e.properties as Record<string, unknown>) || {}),\n },\n };\n });\n }\n\n private getProperty(vertex: unknown, key: string): unknown {\n const v = vertex as Record<string, unknown>;\n const properties = v.properties as Record<string, unknown> | undefined;\n if (properties?.[key]) {\n const prop = properties[key];\n if (Array.isArray(prop)) return (prop[0] as Record<string, unknown>)?.value ?? prop[0];\n if (typeof prop === 'object' && prop !== null && 'value' in (prop as Record<string, unknown>)) return (prop as Record<string, unknown>).value;\n return prop;\n }\n return undefined;\n }\n\n private paginate(items: NodeData[], pagination?: PaginationOptions): PaginatedResult<NodeData> {\n const total = items.length;\n if (!pagination) return { items, total, hasMore: false };\n const { offset, limit } = pagination;\n const sliced = items.slice(offset, offset + limit);\n return { items: sliced, total, hasMore: offset + limit < total };\n }\n}\n","import { GremlinDataSource } from './GremlinDataSource.js';\nimport type { GremlinDataSourceConfig } from './types.js';\n\n/**\n * Factory function that returns a configured `GremlinDataSource`. This is\n * the recommended on-ramp — the package internalizes Gremlin SDK\n * construction (storage owns SDK setup), so callers only supply domain\n * config (endpoint, auth, partition resolver, etc.).\n *\n * Direct `new GremlinDataSource(config)` construction is the escape hatch\n * for subclasses or callers that want to bypass the factory.\n */\nexport function gremlinDataSource(\n config: GremlinDataSourceConfig,\n): GremlinDataSource {\n return new GremlinDataSource(config);\n}\n"],"mappings":"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","names":["gremlin"]}

@@ -1,2 +0,2 @@

import { DataSource, DataAdapterConfig, GraphData, NodeId, NodeData, PaginationOptions, PaginatedResult, DataFilter, ContentData } from '@inferagraph/core';
import { DataSource, DataAdapterConfig, GraphData, NodeId, NodeData, PaginationOptions, PaginatedResult, DataFilter, ContentData } from '@inferagraph/core/data';

@@ -3,0 +3,0 @@ /**

@@ -1,2 +0,2 @@

import { DataSource, DataAdapterConfig, GraphData, NodeId, NodeData, PaginationOptions, PaginatedResult, DataFilter, ContentData } from '@inferagraph/core';
import { DataSource, DataAdapterConfig, GraphData, NodeId, NodeData, PaginationOptions, PaginatedResult, DataFilter, ContentData } from '@inferagraph/core/data';

@@ -3,0 +3,0 @@ /**

// src/GremlinDataSource.ts
import { DataSource } from "@inferagraph/core";
import { DataSource } from "@inferagraph/core/data";
import gremlin from "gremlin";

@@ -4,0 +4,0 @@ var { driver } = gremlin;

@@ -1,1 +0,1 @@

{"version":3,"sources":["../src/GremlinDataSource.ts","../src/factory.ts"],"sourcesContent":["import { DataSource } from '@inferagraph/core';\nimport type {\n DataAdapterConfig, GraphData, NodeId, NodeData, EdgeData,\n ContentData, PaginationOptions, PaginatedResult, DataFilter,\n} from '@inferagraph/core';\nimport gremlin from 'gremlin';\nimport type { GremlinDataSourceConfig, GremlinVertex } from './types.js';\n\nconst { driver } = gremlin;\n\nexport class GremlinDataSource extends DataSource {\n readonly name = 'gremlin';\n private client: InstanceType<typeof driver.Client> | null = null;\n private config: GremlinDataSourceConfig;\n private nameProperty: string;\n\n constructor(config: GremlinDataSourceConfig) {\n super();\n this.config = config;\n this.nameProperty = config.nameProperty ?? 'name';\n }\n\n async connect(): Promise<void> {\n const authenticator = this.config.key\n ? new driver.auth.PlainTextSaslAuthenticator(\n `/dbs/${this.config.database}/colls/${this.config.container}`,\n this.config.key,\n )\n : undefined;\n\n this.client = new driver.Client(this.config.endpoint, {\n authenticator,\n traversalsource: 'g',\n rejectUnauthorized: true,\n mimeType: 'application/vnd.gremlin-v2.0+json',\n });\n\n await this.client.open();\n }\n\n async disconnect(): Promise<void> {\n if (this.client) {\n await this.client.close();\n this.client = null;\n }\n }\n\n isConnected(): boolean {\n return this.client !== null;\n }\n\n async getInitialView(config?: DataAdapterConfig): Promise<GraphData> {\n this.ensureConnected();\n const limit = (config?.limit as number) ?? 100;\n\n // Get vertices\n const vertexResult = await this.client!.submit(`g.V().limit(${limit})`);\n const nodes = this.transformVertices(vertexResult._items || []);\n\n // Get edges between those vertices\n const nodeIds = nodes.map(n => n.id);\n if (nodeIds.length === 0) return { nodes: [], edges: [] };\n\n const edges = await this.fetchEdgesAmongNodes(nodeIds);\n return { nodes, edges };\n }\n\n async getNode(id: NodeId): Promise<NodeData | undefined> {\n this.ensureConnected();\n const result = await this.client!.submit(`g.V(${this.formatKey(this.resolveKey(id))})`);\n const items = result._items || [];\n if (items.length === 0) return undefined;\n return this.transformVertices(items)[0];\n }\n\n async getNeighbors(nodeId: NodeId, depth: number = 1): Promise<GraphData> {\n this.ensureConnected();\n\n const inlinedKey = this.formatKey(this.resolveKey(nodeId));\n\n // Get neighbors up to depth\n const vertexResult = await this.client!.submit(\n `g.V(${inlinedKey}).repeat(both().simplePath()).times(depth).dedup()`,\n { depth },\n );\n const neighborNodes = this.transformVertices(vertexResult._items || []);\n\n // Also get the origin node\n const originResult = await this.client!.submit(`g.V(${inlinedKey})`);\n const originNodes = this.transformVertices(originResult._items || []);\n\n const allNodes = [...originNodes, ...neighborNodes];\n const allNodeIds = allNodes.map(n => n.id);\n\n const edges = await this.fetchEdgesAmongNodes(allNodeIds);\n return { nodes: allNodes, edges };\n }\n\n async findPath(fromId: NodeId, toId: NodeId): Promise<GraphData> {\n this.ensureConnected();\n\n // Termination uses `has(T.id, toId)` rather than `hasId(toId)`. The\n // canonical T.id token compares the document id on Cosmos and the\n // vertex id on TinkerPop, and unlike `hasId()` it accepts a plain\n // id (NOT a composite-key tuple) — which is what we want here, since\n // the bound `toId` is the raw vertex id, not the partition pair.\n //\n // `fromId` is inlined as a Gremlin literal because Cosmos parameter\n // bindings reject lists of tuples; see formatKey().\n const inlinedFrom = this.formatKey(this.resolveKey(fromId));\n const result = await this.client!.submit(\n `g.V(${inlinedFrom}).repeat(both().simplePath()).until(has(T.id, toId)).limit(1).path()`,\n { toId },\n );\n\n const items = result._items || [];\n if (items.length === 0) return { nodes: [], edges: [] };\n\n // Extract path objects\n const pathObjects = items[0]?.objects || [];\n const nodes: NodeData[] = [];\n\n for (const obj of pathObjects) {\n if (obj.id && obj.label && !obj.inV) {\n nodes.push(this.transformVertex(obj));\n }\n }\n\n // Get edges between path nodes\n const nodeIds = nodes.map(n => n.id);\n const pathEdges = await this.fetchEdgesAmongNodes(nodeIds);\n return { nodes, edges: pathEdges };\n }\n\n async search(query: string, pagination?: PaginationOptions): Promise<PaginatedResult<NodeData>> {\n this.ensureConnected();\n\n const result = await this.client!.submit(\n `g.V().has('${this.nameProperty}', TextP.containing(query))`,\n { query },\n );\n\n const allItems = this.transformVertices(result._items || []);\n return this.paginate(allItems, pagination);\n }\n\n async filter(filter: DataFilter, pagination?: PaginationOptions): Promise<PaginatedResult<NodeData>> {\n this.ensureConnected();\n\n // Build Gremlin traversal dynamically\n let traversal = 'g.V()';\n const bindings: Record<string, unknown> = {};\n\n if (filter.types?.length) {\n traversal += `.has('type', within(types))`;\n bindings.types = filter.types;\n }\n if (filter.search) {\n traversal += `.has('${this.nameProperty}', TextP.containing(searchText))`;\n bindings.searchText = filter.search;\n }\n if (filter.attributes) {\n let i = 0;\n for (const [key, value] of Object.entries(filter.attributes)) {\n traversal += `.has(attrKey${i}, attrVal${i})`;\n bindings[`attrKey${i}`] = key;\n bindings[`attrVal${i}`] = value;\n i++;\n }\n }\n\n const result = await this.client!.submit(traversal, bindings);\n const allItems = this.transformVertices(result._items || []);\n return this.paginate(allItems, pagination);\n }\n\n async getContent(nodeId: NodeId): Promise<ContentData | undefined> {\n this.ensureConnected();\n\n const inlinedKey = this.formatKey(this.resolveKey(nodeId));\n const result = await this.client!.submit(\n `g.V(${inlinedKey}).has('content')`,\n );\n\n const items = result._items || [];\n if (items.length === 0) return undefined;\n\n const vertex = items[0];\n const content = this.getProperty(vertex, 'content');\n if (!content) return undefined;\n\n return {\n nodeId,\n content: String(content),\n contentType: (this.getProperty(vertex, 'contentType') as string) ?? 'text',\n };\n }\n\n // --- Private Helpers ---\n\n private ensureConnected(): void {\n if (!this.client) {\n throw new Error('GremlinDataSource is not connected. Call connect() first.');\n }\n }\n\n /**\n * Resolve a vertex id into the value passed to g.V(...).\n * Default: identity (TinkerPop / unpartitioned).\n * If `getCompositeKey` is configured (e.g. for Cosmos DB partitioned\n * containers), delegates to that callback.\n */\n private resolveKey(id: string): string | [string, string] {\n return this.config.getCompositeKey?.(id) ?? id;\n }\n\n /**\n * Format a resolved key as a Gremlin literal to inline into the query.\n *\n * Why inline rather than bind? Cosmos DB Gremlin parameter bindings only\n * accept scalars or arrays of scalars — bindings can NOT carry tuples\n * (`[pk, id]`) nor arrays of tuples. When `getCompositeKey` returns a\n * tuple, the only portable option is to inline the value into the query\n * string. We always inline (even for the scalar case) for consistency.\n *\n * String escaping: Gremlin string literals use single quotes. The\n * untrusted-input risk is small (ids come from host code) but the library\n * defends anyway: backslashes become `\\\\` and single quotes become `\\'`.\n */\n private formatKey(key: string | [string, string]): string {\n if (Array.isArray(key)) {\n return `[${this.escapeString(key[0])}, ${this.escapeString(key[1])}]`;\n }\n return this.escapeString(key);\n }\n\n private escapeString(value: string): string {\n return `'${value.replace(/\\\\/g, '\\\\\\\\').replace(/'/g, \"\\\\'\")}'`;\n }\n\n /**\n * Fetch edges among a known set of vertices.\n *\n * The traversal is `g.V(<inlined keys>).bothE().dedup()` — composite-key\n * safe (each key may be a tuple, inlined directly into the query) and\n * avoids `within(<list-of-tuples>)`, which is unreliable on Cosmos DB\n * Gremlin. We then drop edges with an endpoint outside the `nodeIds`\n * set client-side, since `bothE()` includes edges to neighbors we did\n * not request.\n */\n private async fetchEdgesAmongNodes(nodeIds: string[]): Promise<EdgeData[]> {\n const inlinedKeys = nodeIds\n .map(nid => this.formatKey(this.resolveKey(nid)))\n .join(', ');\n const result = await this.client!.submit(\n `g.V(${inlinedKeys}).bothE().dedup()`,\n );\n const allEdges = this.transformEdges(result._items || []);\n const idSet = new Set(nodeIds);\n return allEdges.filter(e => idSet.has(e.sourceId) && idSet.has(e.targetId));\n }\n\n private transformVertices(items: unknown[]): NodeData[] {\n return items.map(item => this.transformVertex(item));\n }\n\n private transformVertex(vertex: unknown): NodeData {\n const v = vertex as Record<string, unknown>;\n const id = String(v.id);\n const attributes: Record<string, unknown> = {};\n\n // Resolve the semantic type of the vertex. Default = Gremlin label\n // (TinkerPop convention). Hosts whose data stores a constant label\n // and the real type in a property (e.g. Bible Graph: every vertex\n // labeled 'Unit', actual type on a `type` property) override via\n // `getType` to surface the right value. If getType returns undefined,\n // fall back to the label.\n const resolvedType = this.config.getType?.(v as unknown as GremlinVertex) ?? (v.label as string | undefined);\n if (resolvedType !== undefined) attributes.type = resolvedType;\n\n // Gremlin properties can be nested objects\n const properties = v.properties as Record<string, unknown> | undefined;\n if (properties) {\n for (const [key, val] of Object.entries(properties)) {\n if (Array.isArray(val)) {\n // Multi-value property\n attributes[key] = val.length === 1\n ? (val[0] as Record<string, unknown>)?.value ?? val[0]\n : val.map((item: unknown) => (item as Record<string, unknown>)?.value ?? item);\n } else if (typeof val === 'object' && val !== null && 'value' in (val as Record<string, unknown>)) {\n attributes[key] = (val as Record<string, unknown>).value;\n } else {\n attributes[key] = val;\n }\n }\n }\n\n return { id, attributes };\n }\n\n private transformEdges(items: unknown[]): EdgeData[] {\n return items.map((edge: unknown) => {\n const e = edge as Record<string, unknown>;\n const outV = e.outV as Record<string, unknown> | string | undefined;\n const inV = e.inV as Record<string, unknown> | string | undefined;\n return {\n id: String(e.id),\n sourceId: String(typeof outV === 'object' && outV !== null ? outV.id : outV),\n targetId: String(typeof inV === 'object' && inV !== null ? inV.id : inV),\n attributes: {\n type: (e.label as string) ?? '',\n ...((e.properties as Record<string, unknown>) || {}),\n },\n };\n });\n }\n\n private getProperty(vertex: unknown, key: string): unknown {\n const v = vertex as Record<string, unknown>;\n const properties = v.properties as Record<string, unknown> | undefined;\n if (properties?.[key]) {\n const prop = properties[key];\n if (Array.isArray(prop)) return (prop[0] as Record<string, unknown>)?.value ?? prop[0];\n if (typeof prop === 'object' && prop !== null && 'value' in (prop as Record<string, unknown>)) return (prop as Record<string, unknown>).value;\n return prop;\n }\n return undefined;\n }\n\n private paginate(items: NodeData[], pagination?: PaginationOptions): PaginatedResult<NodeData> {\n const total = items.length;\n if (!pagination) return { items, total, hasMore: false };\n const { offset, limit } = pagination;\n const sliced = items.slice(offset, offset + limit);\n return { items: sliced, total, hasMore: offset + limit < total };\n }\n}\n","import { GremlinDataSource } from './GremlinDataSource.js';\nimport type { GremlinDataSourceConfig } from './types.js';\n\n/**\n * Factory function that returns a configured `GremlinDataSource`. This is\n * the recommended on-ramp — the package internalizes Gremlin SDK\n * construction (storage owns SDK setup), so callers only supply domain\n * config (endpoint, auth, partition resolver, etc.).\n *\n * Direct `new GremlinDataSource(config)` construction is the escape hatch\n * for subclasses or callers that want to bypass the factory.\n */\nexport function gremlinDataSource(\n config: GremlinDataSourceConfig,\n): GremlinDataSource {\n return new GremlinDataSource(config);\n}\n"],"mappings":"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","names":[]}
{"version":3,"sources":["../src/GremlinDataSource.ts","../src/factory.ts"],"sourcesContent":["import { DataSource } from '@inferagraph/core/data';\nimport type {\n DataAdapterConfig, GraphData, NodeId, NodeData, EdgeData,\n ContentData, PaginationOptions, PaginatedResult, DataFilter,\n} from '@inferagraph/core/data';\nimport gremlin from 'gremlin';\nimport type { GremlinDataSourceConfig, GremlinVertex } from './types.js';\n\nconst { driver } = gremlin;\n\nexport class GremlinDataSource extends DataSource {\n readonly name = 'gremlin';\n private client: InstanceType<typeof driver.Client> | null = null;\n private config: GremlinDataSourceConfig;\n private nameProperty: string;\n\n constructor(config: GremlinDataSourceConfig) {\n super();\n this.config = config;\n this.nameProperty = config.nameProperty ?? 'name';\n }\n\n async connect(): Promise<void> {\n const authenticator = this.config.key\n ? new driver.auth.PlainTextSaslAuthenticator(\n `/dbs/${this.config.database}/colls/${this.config.container}`,\n this.config.key,\n )\n : undefined;\n\n this.client = new driver.Client(this.config.endpoint, {\n authenticator,\n traversalsource: 'g',\n rejectUnauthorized: true,\n mimeType: 'application/vnd.gremlin-v2.0+json',\n });\n\n await this.client.open();\n }\n\n async disconnect(): Promise<void> {\n if (this.client) {\n await this.client.close();\n this.client = null;\n }\n }\n\n isConnected(): boolean {\n return this.client !== null;\n }\n\n async getInitialView(config?: DataAdapterConfig): Promise<GraphData> {\n this.ensureConnected();\n const limit = (config?.limit as number) ?? 100;\n\n // Get vertices\n const vertexResult = await this.client!.submit(`g.V().limit(${limit})`);\n const nodes = this.transformVertices(vertexResult._items || []);\n\n // Get edges between those vertices\n const nodeIds = nodes.map(n => n.id);\n if (nodeIds.length === 0) return { nodes: [], edges: [] };\n\n const edges = await this.fetchEdgesAmongNodes(nodeIds);\n return { nodes, edges };\n }\n\n async getNode(id: NodeId): Promise<NodeData | undefined> {\n this.ensureConnected();\n const result = await this.client!.submit(`g.V(${this.formatKey(this.resolveKey(id))})`);\n const items = result._items || [];\n if (items.length === 0) return undefined;\n return this.transformVertices(items)[0];\n }\n\n async getNeighbors(nodeId: NodeId, depth: number = 1): Promise<GraphData> {\n this.ensureConnected();\n\n const inlinedKey = this.formatKey(this.resolveKey(nodeId));\n\n // Get neighbors up to depth\n const vertexResult = await this.client!.submit(\n `g.V(${inlinedKey}).repeat(both().simplePath()).times(depth).dedup()`,\n { depth },\n );\n const neighborNodes = this.transformVertices(vertexResult._items || []);\n\n // Also get the origin node\n const originResult = await this.client!.submit(`g.V(${inlinedKey})`);\n const originNodes = this.transformVertices(originResult._items || []);\n\n const allNodes = [...originNodes, ...neighborNodes];\n const allNodeIds = allNodes.map(n => n.id);\n\n const edges = await this.fetchEdgesAmongNodes(allNodeIds);\n return { nodes: allNodes, edges };\n }\n\n async findPath(fromId: NodeId, toId: NodeId): Promise<GraphData> {\n this.ensureConnected();\n\n // Termination uses `has(T.id, toId)` rather than `hasId(toId)`. The\n // canonical T.id token compares the document id on Cosmos and the\n // vertex id on TinkerPop, and unlike `hasId()` it accepts a plain\n // id (NOT a composite-key tuple) — which is what we want here, since\n // the bound `toId` is the raw vertex id, not the partition pair.\n //\n // `fromId` is inlined as a Gremlin literal because Cosmos parameter\n // bindings reject lists of tuples; see formatKey().\n const inlinedFrom = this.formatKey(this.resolveKey(fromId));\n const result = await this.client!.submit(\n `g.V(${inlinedFrom}).repeat(both().simplePath()).until(has(T.id, toId)).limit(1).path()`,\n { toId },\n );\n\n const items = result._items || [];\n if (items.length === 0) return { nodes: [], edges: [] };\n\n // Extract path objects\n const pathObjects = items[0]?.objects || [];\n const nodes: NodeData[] = [];\n\n for (const obj of pathObjects) {\n if (obj.id && obj.label && !obj.inV) {\n nodes.push(this.transformVertex(obj));\n }\n }\n\n // Get edges between path nodes\n const nodeIds = nodes.map(n => n.id);\n const pathEdges = await this.fetchEdgesAmongNodes(nodeIds);\n return { nodes, edges: pathEdges };\n }\n\n async search(query: string, pagination?: PaginationOptions): Promise<PaginatedResult<NodeData>> {\n this.ensureConnected();\n\n const result = await this.client!.submit(\n `g.V().has('${this.nameProperty}', TextP.containing(query))`,\n { query },\n );\n\n const allItems = this.transformVertices(result._items || []);\n return this.paginate(allItems, pagination);\n }\n\n async filter(filter: DataFilter, pagination?: PaginationOptions): Promise<PaginatedResult<NodeData>> {\n this.ensureConnected();\n\n // Build Gremlin traversal dynamically\n let traversal = 'g.V()';\n const bindings: Record<string, unknown> = {};\n\n if (filter.types?.length) {\n traversal += `.has('type', within(types))`;\n bindings.types = filter.types;\n }\n if (filter.search) {\n traversal += `.has('${this.nameProperty}', TextP.containing(searchText))`;\n bindings.searchText = filter.search;\n }\n if (filter.attributes) {\n let i = 0;\n for (const [key, value] of Object.entries(filter.attributes)) {\n traversal += `.has(attrKey${i}, attrVal${i})`;\n bindings[`attrKey${i}`] = key;\n bindings[`attrVal${i}`] = value;\n i++;\n }\n }\n\n const result = await this.client!.submit(traversal, bindings);\n const allItems = this.transformVertices(result._items || []);\n return this.paginate(allItems, pagination);\n }\n\n async getContent(nodeId: NodeId): Promise<ContentData | undefined> {\n this.ensureConnected();\n\n const inlinedKey = this.formatKey(this.resolveKey(nodeId));\n const result = await this.client!.submit(\n `g.V(${inlinedKey}).has('content')`,\n );\n\n const items = result._items || [];\n if (items.length === 0) return undefined;\n\n const vertex = items[0];\n const content = this.getProperty(vertex, 'content');\n if (!content) return undefined;\n\n return {\n nodeId,\n content: String(content),\n contentType: (this.getProperty(vertex, 'contentType') as string) ?? 'text',\n };\n }\n\n // --- Private Helpers ---\n\n private ensureConnected(): void {\n if (!this.client) {\n throw new Error('GremlinDataSource is not connected. Call connect() first.');\n }\n }\n\n /**\n * Resolve a vertex id into the value passed to g.V(...).\n * Default: identity (TinkerPop / unpartitioned).\n * If `getCompositeKey` is configured (e.g. for Cosmos DB partitioned\n * containers), delegates to that callback.\n */\n private resolveKey(id: string): string | [string, string] {\n return this.config.getCompositeKey?.(id) ?? id;\n }\n\n /**\n * Format a resolved key as a Gremlin literal to inline into the query.\n *\n * Why inline rather than bind? Cosmos DB Gremlin parameter bindings only\n * accept scalars or arrays of scalars — bindings can NOT carry tuples\n * (`[pk, id]`) nor arrays of tuples. When `getCompositeKey` returns a\n * tuple, the only portable option is to inline the value into the query\n * string. We always inline (even for the scalar case) for consistency.\n *\n * String escaping: Gremlin string literals use single quotes. The\n * untrusted-input risk is small (ids come from host code) but the library\n * defends anyway: backslashes become `\\\\` and single quotes become `\\'`.\n */\n private formatKey(key: string | [string, string]): string {\n if (Array.isArray(key)) {\n return `[${this.escapeString(key[0])}, ${this.escapeString(key[1])}]`;\n }\n return this.escapeString(key);\n }\n\n private escapeString(value: string): string {\n return `'${value.replace(/\\\\/g, '\\\\\\\\').replace(/'/g, \"\\\\'\")}'`;\n }\n\n /**\n * Fetch edges among a known set of vertices.\n *\n * The traversal is `g.V(<inlined keys>).bothE().dedup()` — composite-key\n * safe (each key may be a tuple, inlined directly into the query) and\n * avoids `within(<list-of-tuples>)`, which is unreliable on Cosmos DB\n * Gremlin. We then drop edges with an endpoint outside the `nodeIds`\n * set client-side, since `bothE()` includes edges to neighbors we did\n * not request.\n */\n private async fetchEdgesAmongNodes(nodeIds: string[]): Promise<EdgeData[]> {\n const inlinedKeys = nodeIds\n .map(nid => this.formatKey(this.resolveKey(nid)))\n .join(', ');\n const result = await this.client!.submit(\n `g.V(${inlinedKeys}).bothE().dedup()`,\n );\n const allEdges = this.transformEdges(result._items || []);\n const idSet = new Set(nodeIds);\n return allEdges.filter(e => idSet.has(e.sourceId) && idSet.has(e.targetId));\n }\n\n private transformVertices(items: unknown[]): NodeData[] {\n return items.map(item => this.transformVertex(item));\n }\n\n private transformVertex(vertex: unknown): NodeData {\n const v = vertex as Record<string, unknown>;\n const id = String(v.id);\n const attributes: Record<string, unknown> = {};\n\n // Resolve the semantic type of the vertex. Default = Gremlin label\n // (TinkerPop convention). Hosts whose data stores a constant label\n // and the real type in a property (e.g. Bible Graph: every vertex\n // labeled 'Unit', actual type on a `type` property) override via\n // `getType` to surface the right value. If getType returns undefined,\n // fall back to the label.\n const resolvedType = this.config.getType?.(v as unknown as GremlinVertex) ?? (v.label as string | undefined);\n if (resolvedType !== undefined) attributes.type = resolvedType;\n\n // Gremlin properties can be nested objects\n const properties = v.properties as Record<string, unknown> | undefined;\n if (properties) {\n for (const [key, val] of Object.entries(properties)) {\n if (Array.isArray(val)) {\n // Multi-value property\n attributes[key] = val.length === 1\n ? (val[0] as Record<string, unknown>)?.value ?? val[0]\n : val.map((item: unknown) => (item as Record<string, unknown>)?.value ?? item);\n } else if (typeof val === 'object' && val !== null && 'value' in (val as Record<string, unknown>)) {\n attributes[key] = (val as Record<string, unknown>).value;\n } else {\n attributes[key] = val;\n }\n }\n }\n\n return { id, attributes };\n }\n\n private transformEdges(items: unknown[]): EdgeData[] {\n return items.map((edge: unknown) => {\n const e = edge as Record<string, unknown>;\n const outV = e.outV as Record<string, unknown> | string | undefined;\n const inV = e.inV as Record<string, unknown> | string | undefined;\n return {\n id: String(e.id),\n sourceId: String(typeof outV === 'object' && outV !== null ? outV.id : outV),\n targetId: String(typeof inV === 'object' && inV !== null ? inV.id : inV),\n attributes: {\n type: (e.label as string) ?? '',\n ...((e.properties as Record<string, unknown>) || {}),\n },\n };\n });\n }\n\n private getProperty(vertex: unknown, key: string): unknown {\n const v = vertex as Record<string, unknown>;\n const properties = v.properties as Record<string, unknown> | undefined;\n if (properties?.[key]) {\n const prop = properties[key];\n if (Array.isArray(prop)) return (prop[0] as Record<string, unknown>)?.value ?? prop[0];\n if (typeof prop === 'object' && prop !== null && 'value' in (prop as Record<string, unknown>)) return (prop as Record<string, unknown>).value;\n return prop;\n }\n return undefined;\n }\n\n private paginate(items: NodeData[], pagination?: PaginationOptions): PaginatedResult<NodeData> {\n const total = items.length;\n if (!pagination) return { items, total, hasMore: false };\n const { offset, limit } = pagination;\n const sliced = items.slice(offset, offset + limit);\n return { items: sliced, total, hasMore: offset + limit < total };\n }\n}\n","import { GremlinDataSource } from './GremlinDataSource.js';\nimport type { GremlinDataSourceConfig } from './types.js';\n\n/**\n * Factory function that returns a configured `GremlinDataSource`. This is\n * the recommended on-ramp — the package internalizes Gremlin SDK\n * construction (storage owns SDK setup), so callers only supply domain\n * config (endpoint, auth, partition resolver, etc.).\n *\n * Direct `new GremlinDataSource(config)` construction is the escape hatch\n * for subclasses or callers that want to bypass the factory.\n */\nexport function gremlinDataSource(\n config: GremlinDataSourceConfig,\n): GremlinDataSource {\n return new GremlinDataSource(config);\n}\n"],"mappings":";AAAA,SAAS,kBAAkB;AAK3B,OAAO,aAAa;AAGpB,IAAM,EAAE,OAAO,IAAI;AAEZ,IAAM,oBAAN,cAAgC,WAAW;AAAA,EACvC,OAAO;AAAA,EACR,SAAoD;AAAA,EACpD;AAAA,EACA;AAAA,EAER,YAAY,QAAiC;AAC3C,UAAM;AACN,SAAK,SAAS;AACd,SAAK,eAAe,OAAO,gBAAgB;AAAA,EAC7C;AAAA,EAEA,MAAM,UAAyB;AAC7B,UAAM,gBAAgB,KAAK,OAAO,MAC9B,IAAI,OAAO,KAAK;AAAA,MACd,QAAQ,KAAK,OAAO,QAAQ,UAAU,KAAK,OAAO,SAAS;AAAA,MAC3D,KAAK,OAAO;AAAA,IACd,IACA;AAEJ,SAAK,SAAS,IAAI,OAAO,OAAO,KAAK,OAAO,UAAU;AAAA,MACpD;AAAA,MACA,iBAAiB;AAAA,MACjB,oBAAoB;AAAA,MACpB,UAAU;AAAA,IACZ,CAAC;AAED,UAAM,KAAK,OAAO,KAAK;AAAA,EACzB;AAAA,EAEA,MAAM,aAA4B;AAChC,QAAI,KAAK,QAAQ;AACf,YAAM,KAAK,OAAO,MAAM;AACxB,WAAK,SAAS;AAAA,IAChB;AAAA,EACF;AAAA,EAEA,cAAuB;AACrB,WAAO,KAAK,WAAW;AAAA,EACzB;AAAA,EAEA,MAAM,eAAe,QAAgD;AACnE,SAAK,gBAAgB;AACrB,UAAM,QAAS,QAAQ,SAAoB;AAG3C,UAAM,eAAe,MAAM,KAAK,OAAQ,OAAO,eAAe,KAAK,GAAG;AACtE,UAAM,QAAQ,KAAK,kBAAkB,aAAa,UAAU,CAAC,CAAC;AAG9D,UAAM,UAAU,MAAM,IAAI,OAAK,EAAE,EAAE;AACnC,QAAI,QAAQ,WAAW,EAAG,QAAO,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,EAAE;AAExD,UAAM,QAAQ,MAAM,KAAK,qBAAqB,OAAO;AACrD,WAAO,EAAE,OAAO,MAAM;AAAA,EACxB;AAAA,EAEA,MAAM,QAAQ,IAA2C;AACvD,SAAK,gBAAgB;AACrB,UAAM,SAAS,MAAM,KAAK,OAAQ,OAAO,OAAO,KAAK,UAAU,KAAK,WAAW,EAAE,CAAC,CAAC,GAAG;AACtF,UAAM,QAAQ,OAAO,UAAU,CAAC;AAChC,QAAI,MAAM,WAAW,EAAG,QAAO;AAC/B,WAAO,KAAK,kBAAkB,KAAK,EAAE,CAAC;AAAA,EACxC;AAAA,EAEA,MAAM,aAAa,QAAgB,QAAgB,GAAuB;AACxE,SAAK,gBAAgB;AAErB,UAAM,aAAa,KAAK,UAAU,KAAK,WAAW,MAAM,CAAC;AAGzD,UAAM,eAAe,MAAM,KAAK,OAAQ;AAAA,MACtC,OAAO,UAAU;AAAA,MACjB,EAAE,MAAM;AAAA,IACV;AACA,UAAM,gBAAgB,KAAK,kBAAkB,aAAa,UAAU,CAAC,CAAC;AAGtE,UAAM,eAAe,MAAM,KAAK,OAAQ,OAAO,OAAO,UAAU,GAAG;AACnE,UAAM,cAAc,KAAK,kBAAkB,aAAa,UAAU,CAAC,CAAC;AAEpE,UAAM,WAAW,CAAC,GAAG,aAAa,GAAG,aAAa;AAClD,UAAM,aAAa,SAAS,IAAI,OAAK,EAAE,EAAE;AAEzC,UAAM,QAAQ,MAAM,KAAK,qBAAqB,UAAU;AACxD,WAAO,EAAE,OAAO,UAAU,MAAM;AAAA,EAClC;AAAA,EAEA,MAAM,SAAS,QAAgB,MAAkC;AAC/D,SAAK,gBAAgB;AAUrB,UAAM,cAAc,KAAK,UAAU,KAAK,WAAW,MAAM,CAAC;AAC1D,UAAM,SAAS,MAAM,KAAK,OAAQ;AAAA,MAChC,OAAO,WAAW;AAAA,MAClB,EAAE,KAAK;AAAA,IACT;AAEA,UAAM,QAAQ,OAAO,UAAU,CAAC;AAChC,QAAI,MAAM,WAAW,EAAG,QAAO,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,EAAE;AAGtD,UAAM,cAAc,MAAM,CAAC,GAAG,WAAW,CAAC;AAC1C,UAAM,QAAoB,CAAC;AAE3B,eAAW,OAAO,aAAa;AAC7B,UAAI,IAAI,MAAM,IAAI,SAAS,CAAC,IAAI,KAAK;AACnC,cAAM,KAAK,KAAK,gBAAgB,GAAG,CAAC;AAAA,MACtC;AAAA,IACF;AAGA,UAAM,UAAU,MAAM,IAAI,OAAK,EAAE,EAAE;AACnC,UAAM,YAAY,MAAM,KAAK,qBAAqB,OAAO;AACzD,WAAO,EAAE,OAAO,OAAO,UAAU;AAAA,EACnC;AAAA,EAEA,MAAM,OAAO,OAAe,YAAoE;AAC9F,SAAK,gBAAgB;AAErB,UAAM,SAAS,MAAM,KAAK,OAAQ;AAAA,MAChC,cAAc,KAAK,YAAY;AAAA,MAC/B,EAAE,MAAM;AAAA,IACV;AAEA,UAAM,WAAW,KAAK,kBAAkB,OAAO,UAAU,CAAC,CAAC;AAC3D,WAAO,KAAK,SAAS,UAAU,UAAU;AAAA,EAC3C;AAAA,EAEA,MAAM,OAAO,QAAoB,YAAoE;AACnG,SAAK,gBAAgB;AAGrB,QAAI,YAAY;AAChB,UAAM,WAAoC,CAAC;AAE3C,QAAI,OAAO,OAAO,QAAQ;AACxB,mBAAa;AACb,eAAS,QAAQ,OAAO;AAAA,IAC1B;AACA,QAAI,OAAO,QAAQ;AACjB,mBAAa,SAAS,KAAK,YAAY;AACvC,eAAS,aAAa,OAAO;AAAA,IAC/B;AACA,QAAI,OAAO,YAAY;AACrB,UAAI,IAAI;AACR,iBAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,OAAO,UAAU,GAAG;AAC5D,qBAAa,eAAe,CAAC,YAAY,CAAC;AAC1C,iBAAS,UAAU,CAAC,EAAE,IAAI;AAC1B,iBAAS,UAAU,CAAC,EAAE,IAAI;AAC1B;AAAA,MACF;AAAA,IACF;AAEA,UAAM,SAAS,MAAM,KAAK,OAAQ,OAAO,WAAW,QAAQ;AAC5D,UAAM,WAAW,KAAK,kBAAkB,OAAO,UAAU,CAAC,CAAC;AAC3D,WAAO,KAAK,SAAS,UAAU,UAAU;AAAA,EAC3C;AAAA,EAEA,MAAM,WAAW,QAAkD;AACjE,SAAK,gBAAgB;AAErB,UAAM,aAAa,KAAK,UAAU,KAAK,WAAW,MAAM,CAAC;AACzD,UAAM,SAAS,MAAM,KAAK,OAAQ;AAAA,MAChC,OAAO,UAAU;AAAA,IACnB;AAEA,UAAM,QAAQ,OAAO,UAAU,CAAC;AAChC,QAAI,MAAM,WAAW,EAAG,QAAO;AAE/B,UAAM,SAAS,MAAM,CAAC;AACtB,UAAM,UAAU,KAAK,YAAY,QAAQ,SAAS;AAClD,QAAI,CAAC,QAAS,QAAO;AAErB,WAAO;AAAA,MACL;AAAA,MACA,SAAS,OAAO,OAAO;AAAA,MACvB,aAAc,KAAK,YAAY,QAAQ,aAAa,KAAgB;AAAA,IACtE;AAAA,EACF;AAAA;AAAA,EAIQ,kBAAwB;AAC9B,QAAI,CAAC,KAAK,QAAQ;AAChB,YAAM,IAAI,MAAM,2DAA2D;AAAA,IAC7E;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQQ,WAAW,IAAuC;AACxD,WAAO,KAAK,OAAO,kBAAkB,EAAE,KAAK;AAAA,EAC9C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAeQ,UAAU,KAAwC;AACxD,QAAI,MAAM,QAAQ,GAAG,GAAG;AACtB,aAAO,IAAI,KAAK,aAAa,IAAI,CAAC,CAAC,CAAC,KAAK,KAAK,aAAa,IAAI,CAAC,CAAC,CAAC;AAAA,IACpE;AACA,WAAO,KAAK,aAAa,GAAG;AAAA,EAC9B;AAAA,EAEQ,aAAa,OAAuB;AAC1C,WAAO,IAAI,MAAM,QAAQ,OAAO,MAAM,EAAE,QAAQ,MAAM,KAAK,CAAC;AAAA,EAC9D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAc,qBAAqB,SAAwC;AACzE,UAAM,cAAc,QACjB,IAAI,SAAO,KAAK,UAAU,KAAK,WAAW,GAAG,CAAC,CAAC,EAC/C,KAAK,IAAI;AACZ,UAAM,SAAS,MAAM,KAAK,OAAQ;AAAA,MAChC,OAAO,WAAW;AAAA,IACpB;AACA,UAAM,WAAW,KAAK,eAAe,OAAO,UAAU,CAAC,CAAC;AACxD,UAAM,QAAQ,IAAI,IAAI,OAAO;AAC7B,WAAO,SAAS,OAAO,OAAK,MAAM,IAAI,EAAE,QAAQ,KAAK,MAAM,IAAI,EAAE,QAAQ,CAAC;AAAA,EAC5E;AAAA,EAEQ,kBAAkB,OAA8B;AACtD,WAAO,MAAM,IAAI,UAAQ,KAAK,gBAAgB,IAAI,CAAC;AAAA,EACrD;AAAA,EAEQ,gBAAgB,QAA2B;AACjD,UAAM,IAAI;AACV,UAAM,KAAK,OAAO,EAAE,EAAE;AACtB,UAAM,aAAsC,CAAC;AAQ7C,UAAM,eAAe,KAAK,OAAO,UAAU,CAA6B,KAAM,EAAE;AAChF,QAAI,iBAAiB,OAAW,YAAW,OAAO;AAGlD,UAAM,aAAa,EAAE;AACrB,QAAI,YAAY;AACd,iBAAW,CAAC,KAAK,GAAG,KAAK,OAAO,QAAQ,UAAU,GAAG;AACnD,YAAI,MAAM,QAAQ,GAAG,GAAG;AAEtB,qBAAW,GAAG,IAAI,IAAI,WAAW,IAC5B,IAAI,CAAC,GAA+B,SAAS,IAAI,CAAC,IACnD,IAAI,IAAI,CAAC,SAAmB,MAAkC,SAAS,IAAI;AAAA,QACjF,WAAW,OAAO,QAAQ,YAAY,QAAQ,QAAQ,WAAY,KAAiC;AACjG,qBAAW,GAAG,IAAK,IAAgC;AAAA,QACrD,OAAO;AACL,qBAAW,GAAG,IAAI;AAAA,QACpB;AAAA,MACF;AAAA,IACF;AAEA,WAAO,EAAE,IAAI,WAAW;AAAA,EAC1B;AAAA,EAEQ,eAAe,OAA8B;AACnD,WAAO,MAAM,IAAI,CAAC,SAAkB;AAClC,YAAM,IAAI;AACV,YAAM,OAAO,EAAE;AACf,YAAM,MAAM,EAAE;AACd,aAAO;AAAA,QACL,IAAI,OAAO,EAAE,EAAE;AAAA,QACf,UAAU,OAAO,OAAO,SAAS,YAAY,SAAS,OAAO,KAAK,KAAK,IAAI;AAAA,QAC3E,UAAU,OAAO,OAAO,QAAQ,YAAY,QAAQ,OAAO,IAAI,KAAK,GAAG;AAAA,QACvE,YAAY;AAAA,UACV,MAAO,EAAE,SAAoB;AAAA,UAC7B,GAAK,EAAE,cAA0C,CAAC;AAAA,QACpD;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEQ,YAAY,QAAiB,KAAsB;AACzD,UAAM,IAAI;AACV,UAAM,aAAa,EAAE;AACrB,QAAI,aAAa,GAAG,GAAG;AACrB,YAAM,OAAO,WAAW,GAAG;AAC3B,UAAI,MAAM,QAAQ,IAAI,EAAG,QAAQ,KAAK,CAAC,GAA+B,SAAS,KAAK,CAAC;AACrF,UAAI,OAAO,SAAS,YAAY,SAAS,QAAQ,WAAY,KAAkC,QAAQ,KAAiC;AACxI,aAAO;AAAA,IACT;AACA,WAAO;AAAA,EACT;AAAA,EAEQ,SAAS,OAAmB,YAA2D;AAC7F,UAAM,QAAQ,MAAM;AACpB,QAAI,CAAC,WAAY,QAAO,EAAE,OAAO,OAAO,SAAS,MAAM;AACvD,UAAM,EAAE,QAAQ,MAAM,IAAI;AAC1B,UAAM,SAAS,MAAM,MAAM,QAAQ,SAAS,KAAK;AACjD,WAAO,EAAE,OAAO,QAAQ,OAAO,SAAS,SAAS,QAAQ,MAAM;AAAA,EACjE;AACF;;;ACpUO,SAAS,kBACd,QACmB;AACnB,SAAO,IAAI,kBAAkB,MAAM;AACrC;","names":[]}
{
"name": "@inferagraph/gremlin",
"version": "0.2.0",
"version": "0.2.1",
"description": "Apache TinkerPop Gremlin datasource for InferaGraph",
"repository": {
"type": "git",
"url": "git+https://github.com/inferagraph/gremlin-datasource.git"
"url": "git+https://github.com/inferagraph/gremlin.git"
},

@@ -45,3 +45,3 @@ "type": "module",

"devDependencies": {
"@inferagraph/core": "link:../inferagraph",
"@inferagraph/core": "^0.9.1",
"@types/gremlin": "^3.6.7",

@@ -48,0 +48,0 @@ "@vitest/coverage-v8": "^3.1.1",