@kpritam/gremlin-mcp
Version:
A Gremlin MCP server that allows for fetching status, schema, and querying using Gremlin for any Gremlin-compatible graph database (TypeScript implementation).
95 lines • 3.51 kB
JavaScript
/**
* Gremlin result parsing utilities.
*
* This module provides idiomatic parsing of Gremlin query results into
* type-safe, serializable objects using Zod schemas.
*/
import { z } from 'zod';
import { GremlinResultItemSchema } from '../gremlin/models.js';
import { calculateResultMetadata } from './result-metadata.js';
/**
* Type guard for objects with a specific constructor name.
* This is used to identify native Gremlin types from the driver.
*/
function hasConstructorName(obj, name) {
return (obj !== null &&
typeof obj === 'object' &&
'constructor' in obj &&
obj.constructor?.name === name);
}
/**
* A Zod schema that preprocesses raw Gremlin results before validation.
*
* It transforms Gremlin-specific driver types (like Vertex, Edge, Path)
* and data structures (like Map) into a standard format that can be
* validated against the `GremlinResultItemSchema`.
*/
const GremlinPreprocessedResultSchema = z.preprocess((arg) => {
// Pass through primitives and null/undefined, which Zod can handle directly.
if (arg === null || typeof arg !== 'object') {
return arg;
}
// Handle native Gremlin structure types by checking their constructor name
// and transforming them into plain objects with a 'type' discriminator.
if (hasConstructorName(arg, 'Vertex')) {
const rawVertex = arg;
return { ...rawVertex, type: 'vertex' };
}
if (hasConstructorName(arg, 'Edge')) {
const rawEdge = arg;
return { ...rawEdge, type: 'edge' };
}
if (hasConstructorName(arg, 'Path')) {
const rawPath = arg;
return {
labels: Array.isArray(rawPath.labels) ? rawPath.labels.map(String) : [],
objects: rawPath.objects,
type: 'path',
};
}
if (hasConstructorName(arg, 'Property') || hasConstructorName(arg, 'VertexProperty')) {
const rawProp = arg;
return {
key: rawProp.key || rawProp.label || '',
value: rawProp.value,
type: 'property',
};
}
// Convert ES6 Maps to plain objects so Zod can parse them.
if (arg instanceof Map) {
return Object.fromEntries(arg.entries());
}
// If a generic object looks like a vertex or edge (e.g., from a different driver
// or a simple JSON response), add the 'type' discriminator to help Zod parse it.
if ('id' in arg && 'label' in arg) {
if ('properties' in arg && !('inV' in arg) && !('outV' in arg)) {
return { ...arg, type: 'vertex' };
}
if ('inV' in arg && 'outV' in arg) {
return { ...arg, type: 'edge' };
}
}
// Let arrays and other plain objects pass through for Zod to handle.
return arg;
}, GremlinResultItemSchema);
/**
* Parses a single raw Gremlin result item into a typed, serializable object.
*/
export function parseGremlinResultItem(rawResult) {
return GremlinPreprocessedResultSchema.parse(rawResult);
}
/**
* Parses an array of raw Gremlin results into typed objects.
*/
export function parseGremlinResults(rawResults) {
return rawResults.map(parseGremlinResultItem);
}
/**
* Enhanced result parser that provides detailed type information and metadata.
*/
export function parseGremlinResultsWithMetadata(rawResults) {
const results = parseGremlinResults(rawResults);
const metadata = calculateResultMetadata(results);
return { results, metadata };
}
//# sourceMappingURL=result-parser.js.map