You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tinkerpop.apache.org by sp...@apache.org on 2025/10/09 19:47:14 UTC
(tinkerpop) 04/10: TinkerPop prefers edges to relationships in its naming
This is an automated email from the ASF dual-hosted git repository.
spmallette pushed a commit to branch gremlin-mcp
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git
commit 8607ef90b302d86e5424a0742f465cd2abdbf53e
Author: Stephen Mallette <st...@amazon.com>
AuthorDate: Mon Sep 29 16:39:42 2025 -0400
TinkerPop prefers edges to relationships in its naming
---
.../javascript/gremlin-javascript/package.json | 7 ++-
gremlin-tools/gremlin-mcp/README.md | 4 +-
.../{relationship-patterns.ts => edge-patterns.ts} | 20 +++---
.../gremlin-mcp/src/gremlin/models/graph-schema.ts | 30 ++++-----
.../gremlin-mcp/src/gremlin/schema-assembly.ts | 72 +++++++++++-----------
.../gremlin-mcp/src/gremlin/schema-generator.ts | 16 ++---
...ship-patterns.test.ts => edge-patterns.test.ts} | 48 +++++++--------
.../tests/integration/mcp-integration.test.ts | 12 ++--
gremlin-tools/gremlin-mcp/tests/models.test.ts | 24 ++++----
.../gremlin-mcp/tests/schema-assembly.test.ts | 72 +++++++++++-----------
10 files changed, 155 insertions(+), 150 deletions(-)
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/package.json b/gremlin-javascript/src/main/javascript/gremlin-javascript/package.json
index 611a2460ab..6f8b5bde86 100644
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/package.json
+++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/package.json
@@ -2,14 +2,19 @@
"name": "gremlin",
"version": "3.8.0-alpha1",
"description": "JavaScript Gremlin Language Variant",
- "author": "Apache TinkerPop team",
+ "author": {
+ "name": "Apache TinkerPop team"
+ },
"keywords": [
"graph",
"gremlin",
"tinkerpop",
+ "apache-tinkerpop",
"connection",
"glv",
"driver",
+ "graph",
+ "database",
"graphdb"
],
"license": "Apache-2.0",
diff --git a/gremlin-tools/gremlin-mcp/README.md b/gremlin-tools/gremlin-mcp/README.md
index 82692282fb..a42846461f 100644
--- a/gremlin-tools/gremlin-mcp/README.md
+++ b/gremlin-tools/gremlin-mcp/README.md
@@ -42,10 +42,10 @@ Talk to your graph database naturally:
Your AI assistant gets access to these powerful tools:
| Tool | Purpose | What It Does |
-| --------------------------- | ---------------- |--------------------------------------------------------------|
+|-----------------------------| ---------------- |--------------------------------------------------------------|
| 🔍 **get_graph_status** | Health Check | Verify database connectivity and server status |
| 📋 **get_graph_schema** | Schema Discovery | Get complete graph structure with vertices and edges |
-| ⚡ **run_gremlin_query** | Query Execution | Execute any Gremlin traversal query with full syntax support |
+| ⚡ **run_gremlin_query** | Query Execution | Execute any Gremlin traversal query with full syntax support |
| 🔄 **refresh_schema_cache** | Cache Management | Force immediate refresh of cached schema information |
| 📥 **import_graph_data** | Data Import | Load data from GraphSON, CSV, or JSON with batch processing |
| 📤 **export_subgraph** | Data Export | Extract subgraphs to JSON, GraphSON, or CSV formats |
diff --git a/gremlin-tools/gremlin-mcp/src/gremlin/relationship-patterns.ts b/gremlin-tools/gremlin-mcp/src/gremlin/edge-patterns.ts
similarity index 89%
rename from gremlin-tools/gremlin-mcp/src/gremlin/relationship-patterns.ts
rename to gremlin-tools/gremlin-mcp/src/gremlin/edge-patterns.ts
index 6f1c33738f..f70c4fa39e 100644
--- a/gremlin-tools/gremlin-mcp/src/gremlin/relationship-patterns.ts
+++ b/gremlin-tools/gremlin-mcp/src/gremlin/edge-patterns.ts
@@ -27,7 +27,7 @@
import { Effect } from 'effect';
import gremlin from 'gremlin';
-import type { RelationshipPattern } from './models/index.js';
+import type { EdgePattern } from './models/index.js';
import { executeGremlinQuery } from './query-utils.js';
import type { GremlinQueryError } from '../errors.js';
import type { process } from 'gremlin';
@@ -52,12 +52,12 @@ interface RawPatternData {
* @param maxPatterns - Maximum number of patterns to retrieve (default: 1000)
* @returns Effect with array of relationship patterns
*/
-export const generateRelationshipPatterns = (
+export const generateEdgePatterns = (
g: GraphTraversalSource,
maxPatterns: number = 1000
-): Effect.Effect<RelationshipPattern[], GremlinQueryError> =>
+): Effect.Effect<EdgePattern[], GremlinQueryError> =>
Effect.gen(function* () {
- yield* Effect.logInfo('Generating relationship patterns from edge connectivity');
+ yield* Effect.logInfo('Generating edge patterns from edge connectivity');
// Get all patterns in a single optimized query
const allPatterns = yield* executeGremlinQuery(
@@ -71,7 +71,7 @@ export const generateRelationshipPatterns = (
.dedup()
.limit(maxPatterns)
.toList(),
- 'Failed to get relationship patterns',
+ 'Failed to get edge patterns',
`g.E().project('from', 'to', 'label').by(outV().label()).by(inV().label()).by(label()).dedup().limit(${maxPatterns}).toList()`
);
@@ -95,12 +95,12 @@ export const generateRelationshipPatterns = (
*/
const processRawPatterns = (
rawPatterns: unknown[]
-): Effect.Effect<RelationshipPattern[], never> => {
+): Effect.Effect<EdgePattern[], never> => {
// Extract pattern data handling both Map and object formats
const extractedPatterns = rawPatterns.map(extractPatternData);
// Filter out invalid patterns and convert to final format
- const validPatterns = extractedPatterns.filter(isValidPattern).map(convertToRelationshipPattern);
+ const validPatterns = extractedPatterns.filter(isValidPattern).map(convertToEdgePattern);
return Effect.succeed(validPatterns);
};
@@ -150,12 +150,12 @@ const isValidPattern = (pattern: RawPatternData): pattern is Required<RawPattern
typeof pattern.label === 'string';
/**
- * Converts validated pattern data to final RelationshipPattern format.
+ * Converts validated pattern data to final EdgePattern format.
*
* @param pattern - Validated pattern data
* @returns Relationship pattern object
*/
-const convertToRelationshipPattern = (pattern: Required<RawPatternData>): RelationshipPattern => ({
+const convertToEdgePattern = (pattern: Required<RawPatternData>): EdgePattern => ({
left_vertex: pattern.from as string,
right_vertex: pattern.to as string,
relation: pattern.label as string,
@@ -167,7 +167,7 @@ const convertToRelationshipPattern = (pattern: Required<RawPatternData>): Relati
* @param patterns - Array of relationship patterns
* @returns Pattern analysis statistics
*/
-export const analyzePatternStatistics = (patterns: RelationshipPattern[]) => {
+export const analyzePatternStatistics = (patterns: EdgePattern[]) => {
const vertexTypes = new Set<string>();
const edgeTypes = new Set<string>();
const connections = new Map<string, number>();
diff --git a/gremlin-tools/gremlin-mcp/src/gremlin/models/graph-schema.ts b/gremlin-tools/gremlin-mcp/src/gremlin/models/graph-schema.ts
index 60845d4c44..b346337381 100644
--- a/gremlin-tools/gremlin-mcp/src/gremlin/models/graph-schema.ts
+++ b/gremlin-tools/gremlin-mcp/src/gremlin/models/graph-schema.ts
@@ -59,30 +59,30 @@ export type Vertex = z.infer<typeof VertexSchema>;
/**
* Relationship type in the graph schema.
*/
-export const RelationshipSchema = z.object({
- /** The type/category of the relationship */
+export const EdgeSchema = z.object({
+ /** The type/category of the edge */
type: z.string(),
- /** List of properties that can be assigned to this relationship type */
+ /** List of properties that can be assigned to this edge type */
properties: z.array(PropertySchema).default([]),
/** Count of edges with this label */
count: z.number().optional(),
});
-export type Relationship = z.infer<typeof RelationshipSchema>;
+export type Edge = z.infer<typeof EdgeSchema>;
/**
- * Valid relationship pattern between vertices.
+ * Valid edge pattern between vertices.
*/
-export const RelationshipPatternSchema = z.object({
+export const EdgePatternSchema = z.object({
/** The label of the source/starting vertex */
left_vertex: z.string(),
/** The label of the target/ending vertex */
right_vertex: z.string(),
- /** The type of relationship connecting the vertices */
+ /** The label/type of the edge connecting the vertices */
relation: z.string(),
});
-export type RelationshipPattern = z.infer<typeof RelationshipPatternSchema>;
+export type EdgePattern = z.infer<typeof EdgePatternSchema>;
/**
* Schema metadata and optimization settings.
@@ -92,9 +92,9 @@ export const SchemaMetadataSchema = z.object({
schema_size_bytes: z.number().optional(),
/** Number of vertex types */
vertex_count: z.number(),
- /** Number of relationship types */
- relationship_count: z.number(),
- /** Number of relationship patterns */
+ /** Number of edge types */
+ edge_count: z.number(),
+ /** Number of edge patterns */
pattern_count: z.number(),
/** Time taken to generate the schema in milliseconds */
generation_time_ms: z.number().optional(),
@@ -119,10 +119,10 @@ export type SchemaMetadata = z.infer<typeof SchemaMetadataSchema>;
export const GraphSchemaSchema = z.object({
/** List of all vertex types defined in the schema */
vertices: z.array(VertexSchema),
- /** List of all relationship types defined in the schema */
- relationships: z.array(RelationshipSchema),
- /** List of valid relationship patterns between vertices */
- relationship_patterns: z.array(RelationshipPatternSchema),
+ /** List of all edge types defined in the schema */
+ edges: z.array(EdgeSchema),
+ /** List of valid edge patterns between vertices */
+ edge_patterns: z.array(EdgePatternSchema),
/** Schema metadata and optimization information */
metadata: SchemaMetadataSchema.optional(),
});
diff --git a/gremlin-tools/gremlin-mcp/src/gremlin/schema-assembly.ts b/gremlin-tools/gremlin-mcp/src/gremlin/schema-assembly.ts
index 626e4c077d..05345efd70 100644
--- a/gremlin-tools/gremlin-mcp/src/gremlin/schema-assembly.ts
+++ b/gremlin-tools/gremlin-mcp/src/gremlin/schema-assembly.ts
@@ -30,8 +30,8 @@ import {
GraphSchemaSchema,
type GraphSchema,
type Vertex,
- type Relationship,
- type RelationshipPattern,
+ type Edge,
+ type EdgePattern,
} from './models/index.js';
import { Errors, type GremlinQueryError } from '../errors.js';
import type { SchemaConfig } from './types.js';
@@ -43,7 +43,7 @@ export interface SchemaMetadata {
generated_at: string;
generation_time_ms: number;
vertex_count: number;
- relationship_count: number;
+ edge_count: number;
pattern_count: number;
optimization_settings: {
sample_values_included: boolean;
@@ -59,34 +59,34 @@ export interface SchemaMetadata {
* Assembles and validates the final graph schema from analyzed components.
*
* @param vertices - Analyzed vertex types
- * @param relationships - Analyzed edge relationships
- * @param patterns - Relationship patterns
+ * @param edges - Analyzed edges
+ * @param patterns - Edge patterns
* @param config - Schema generation configuration
* @param startTime - Generation start timestamp for performance metrics
* @returns Effect with validated graph schema
*/
export const assembleGraphSchema = (
vertices: Vertex[],
- relationships: Relationship[],
- patterns: RelationshipPattern[],
+ edges: Edge[],
+ patterns: EdgePattern[],
config: SchemaConfig,
startTime: number
): Effect.Effect<GraphSchema, GremlinQueryError> =>
Effect.gen(function* () {
// Create metadata
- const metadata = createSchemaMetadata(vertices, relationships, patterns, config, startTime);
+ const metadata = createSchemaMetadata(vertices, edges, patterns, config, startTime);
// Assemble schema data
const schemaData = {
vertices,
- relationships,
- relationship_patterns: patterns,
+ edges,
+ edge_patterns: patterns,
metadata,
};
yield* Effect.logDebug('Schema assembly completed', {
vertexCount: vertices.length,
- relationshipCount: relationships.length,
+ edgeCount: edges.length,
patternCount: patterns.length,
generationTimeMs: metadata.generation_time_ms,
});
@@ -107,15 +107,15 @@ export const assembleGraphSchema = (
*/
const createSchemaMetadata = (
vertices: Vertex[],
- relationships: Relationship[],
- patterns: RelationshipPattern[],
+ edges: Edge[],
+ patterns: EdgePattern[],
config: SchemaConfig,
startTime: number
): SchemaMetadata => ({
generated_at: new Date().toISOString(),
generation_time_ms: Date.now() - startTime,
vertex_count: vertices.length,
- relationship_count: relationships.length,
+ edge_count: edges.length,
pattern_count: patterns.length,
optimization_settings: {
sample_values_included: config.includeSampleValues,
@@ -200,51 +200,51 @@ export const validateVertices = (vertices: Vertex[]): Effect.Effect<void, Gremli
});
/**
- * Validates relationship data consistency and completeness.
+ * Validates edge data consistency and completeness.
*
- * @param relationships - Array of relationships to validate
+ * @param edges - Array of edges to validate
* @returns Effect with validation result
*/
-export const validateRelationships = (
- relationships: Relationship[]
+export const validateEdges = (
+ edges: Edge[]
): Effect.Effect<void, GremlinQueryError> =>
Effect.gen(function* () {
const issues: string[] = [];
- relationships.forEach((rel, index) => {
- if (!rel.type || typeof rel.type !== 'string') {
- issues.push(`Relationship ${index}: Invalid or missing type`);
+ edges.forEach((edge, index) => {
+ if (!edge.type || typeof edge.type !== 'string') {
+ issues.push(`Edge ${index}: Invalid or missing type`);
}
- if (!Array.isArray(rel.properties)) {
- issues.push(`Relationship ${index}: Properties must be an array`);
+ if (!Array.isArray(edge.properties)) {
+ issues.push(`Edge ${index}: Properties must be an array`);
}
- rel.properties?.forEach((prop, propIndex) => {
+ edge.properties?.forEach((prop, propIndex) => {
if (!prop.name || typeof prop.name !== 'string') {
- issues.push(`Relationship ${index}, Property ${propIndex}: Invalid or missing name`);
+ issues.push(`Edge ${index}, Property ${propIndex}: Invalid or missing name`);
}
if (!Array.isArray(prop.type)) {
- issues.push(`Relationship ${index}, Property ${propIndex}: Type must be an array`);
+ issues.push(`Edge ${index}, Property ${propIndex}: Type must be an array`);
}
});
});
if (issues.length > 0) {
return yield* Effect.fail(
- Errors.query('Relationship validation failed', 'relationship-validation', { issues })
+ Errors.query('Edge validation failed', 'edge-validation', { issues })
);
}
});
/**
- * Validates relationship patterns for consistency.
+ * Validates edge patterns for consistency.
*
- * @param patterns - Array of relationship patterns to validate
+ * @param patterns - Array of edge patterns to validate
* @returns Effect with validation result
*/
-export const validateRelationshipPatterns = (
- patterns: RelationshipPattern[]
+export const validateEdgePatterns = (
+ patterns: EdgePattern[]
): Effect.Effect<void, GremlinQueryError> =>
Effect.gen(function* () {
const issues: string[] = [];
@@ -263,7 +263,7 @@ export const validateRelationshipPatterns = (
if (issues.length > 0) {
return yield* Effect.fail(
- Errors.query('Relationship pattern validation failed', 'pattern-validation', { issues })
+ Errors.query('Edge pattern validation failed', 'pattern-validation', { issues })
);
}
});
@@ -278,13 +278,13 @@ export const validateRelationshipPatterns = (
*/
export const validateAllComponents = (
vertices: Vertex[],
- relationships: Relationship[],
- patterns: RelationshipPattern[]
+ edges: Edge[],
+ patterns: EdgePattern[]
): Effect.Effect<void, GremlinQueryError> =>
Effect.gen(function* () {
yield* validateVertices(vertices);
- yield* validateRelationships(relationships);
- yield* validateRelationshipPatterns(patterns);
+ yield* validateEdges(edges);
+ yield* validateEdgePatterns(patterns);
yield* Effect.logInfo('All schema components validated successfully');
});
diff --git a/gremlin-tools/gremlin-mcp/src/gremlin/schema-generator.ts b/gremlin-tools/gremlin-mcp/src/gremlin/schema-generator.ts
index 9022da0cda..890cf18592 100644
--- a/gremlin-tools/gremlin-mcp/src/gremlin/schema-generator.ts
+++ b/gremlin-tools/gremlin-mcp/src/gremlin/schema-generator.ts
@@ -27,7 +27,7 @@
*/
import { Effect, Duration } from 'effect';
-import { type GraphSchema, type Vertex, type Relationship } from './models/index.js';
+import { type GraphSchema, type Vertex, type Edge } from './models/index.js';
import { Errors, type GremlinConnectionError, type GremlinQueryError } from '../errors.js';
import type { ConnectionState, SchemaConfig } from './types.js';
import {
@@ -39,7 +39,7 @@ import {
getEdgePropertyKeys,
} from './query-utils.js';
import { analyzeElementProperties, withElementCounts } from './property-analyzer.js';
-import { generateRelationshipPatterns } from './relationship-patterns.js';
+import { generateEdgePatterns } from './edge-patterns.js';
import { assembleGraphSchema } from './schema-assembly.js';
import type { process } from 'gremlin';
@@ -88,26 +88,26 @@ const executeSchemaGeneration = (
// Step 3: Analyze properties and patterns in parallel
yield* Effect.logInfo('Analyzing properties and relationship patterns');
- const [rawVertices, rawRelationships, patterns] = yield* Effect.all(
+ const [rawVertices, rawEdges, patterns] = yield* Effect.all(
[
analyzeElementProperties(g, vertexLabels, getVertexPropertyKeys, config, true),
analyzeElementProperties(g, edgeLabels, getEdgePropertyKeys, config, false),
- generateRelationshipPatterns(g),
+ generateEdgePatterns(g),
],
{ concurrency: 3 }
);
// Step 4: Add count information
const vertices = addElementCounts<Vertex>(rawVertices, vertexCounts, config, 'labels');
- const relationships = addElementCounts<Relationship>(
- rawRelationships,
+ const edges = addElementCounts<Edge>(
+ rawEdges,
edgeCounts,
config,
'type'
);
// Step 5: Assemble final schema
- return yield* assembleGraphSchema(vertices, relationships, patterns, config, startTime);
+ return yield* assembleGraphSchema(vertices, edges, patterns, config, startTime);
});
/**
@@ -127,7 +127,7 @@ const getElementCounts = (
/**
* Adds count information to analysis results.
*/
-const addElementCounts = <T extends Vertex | Relationship>(
+const addElementCounts = <T extends Vertex | Edge>(
rawElements: unknown[],
counts: SchemaCountData,
config: SchemaConfig,
diff --git a/gremlin-tools/gremlin-mcp/tests/relationship-patterns.test.ts b/gremlin-tools/gremlin-mcp/tests/edge-patterns.test.ts
similarity index 85%
rename from gremlin-tools/gremlin-mcp/tests/relationship-patterns.test.ts
rename to gremlin-tools/gremlin-mcp/tests/edge-patterns.test.ts
index eea75c892b..5556f005fd 100644
--- a/gremlin-tools/gremlin-mcp/tests/relationship-patterns.test.ts
+++ b/gremlin-tools/gremlin-mcp/tests/edge-patterns.test.ts
@@ -19,20 +19,20 @@
/**
- * @fileoverview Tests for the relationship patterns module.
+ * @fileoverview Tests for the edge patterns module.
*
- * Tests relationship pattern analysis including edge connectivity patterns,
- * pattern processing, and relationship statistics generation.
+ * Tests edge pattern analysis including edge connectivity patterns,
+ * pattern processing, and edge statistics generation.
*/
import { Effect } from 'effect';
import { describe, it, expect, beforeEach, jest } from '@jest/globals';
import {
- generateRelationshipPatterns,
+ generateEdgePatterns as generateEdgePatterns,
analyzePatternStatistics,
-} from '../src/gremlin/relationship-patterns.js';
+} from '../src/gremlin/edge-patterns.js';
import { Errors } from '../src/errors.js';
-import type { RelationshipPattern } from '../src/gremlin/models.js';
+import type { EdgePattern } from '../src/gremlin/models.js';
// Mock Gremlin query utilities
jest.mock('../src/gremlin/query-utils.js', () => ({
@@ -45,24 +45,24 @@ const mockExecuteGremlinQuery = executeGremlinQuery as jest.MockedFunction<
typeof executeGremlinQuery
>;
-describe('relationship-patterns', () => {
+describe('edge-patterns', () => {
beforeEach(() => {
jest.clearAllMocks();
});
- describe('generateRelationshipPatterns', () => {
+ describe('generateEdgePatterns', () => {
const mockTraversalSource = {
E: jest.fn(),
} as any;
- it('should generate relationship patterns successfully', async () => {
+ it('should generate edge patterns successfully', async () => {
const mockRawPatterns = [
{ from: 'person', to: 'company', label: 'worksAt' },
{ from: 'person', to: 'person', label: 'knows' },
{ from: 'company', to: 'project', label: 'sponsors' },
];
- const expectedPatterns: RelationshipPattern[] = [
+ const expectedPatterns: EdgePattern[] = [
{ left_vertex: 'person', right_vertex: 'company', relation: 'worksAt' },
{ left_vertex: 'person', right_vertex: 'person', relation: 'knows' },
{ left_vertex: 'company', right_vertex: 'project', relation: 'sponsors' },
@@ -70,12 +70,12 @@ describe('relationship-patterns', () => {
mockExecuteGremlinQuery.mockReturnValue(Effect.succeed(mockRawPatterns));
- const result = await Effect.runPromise(generateRelationshipPatterns(mockTraversalSource));
+ const result = await Effect.runPromise(generateEdgePatterns(mockTraversalSource));
expect(result).toEqual(expectedPatterns);
expect(mockExecuteGremlinQuery).toHaveBeenCalledWith(
expect.any(Function),
- 'Failed to get relationship patterns',
+ 'Failed to get edge patterns',
expect.stringContaining('project')
);
});
@@ -86,13 +86,13 @@ describe('relationship-patterns', () => {
mockExecuteGremlinQuery.mockReturnValue(Effect.succeed(mockRawPatterns));
const result = await Effect.runPromise(
- generateRelationshipPatterns(mockTraversalSource, 500)
+ generateEdgePatterns(mockTraversalSource, 500)
);
expect(result).toHaveLength(1);
expect(mockExecuteGremlinQuery).toHaveBeenCalledWith(
expect.any(Function),
- 'Failed to get relationship patterns',
+ 'Failed to get edge patterns',
expect.stringContaining('limit(500)')
);
});
@@ -100,7 +100,7 @@ describe('relationship-patterns', () => {
it('should handle empty pattern results', async () => {
mockExecuteGremlinQuery.mockReturnValue(Effect.succeed([]));
- const result = await Effect.runPromise(generateRelationshipPatterns(mockTraversalSource));
+ const result = await Effect.runPromise(generateEdgePatterns(mockTraversalSource));
expect(result).toEqual([]);
});
@@ -115,7 +115,7 @@ describe('relationship-patterns', () => {
mockExecuteGremlinQuery.mockReturnValue(Effect.succeed(mockRawPatterns));
- const result = await Effect.runPromise(generateRelationshipPatterns(mockTraversalSource));
+ const result = await Effect.runPromise(generateEdgePatterns(mockTraversalSource));
// Should filter out invalid patterns and process only valid ones
expect(result).toHaveLength(2); // Only valid patterns processed
@@ -135,7 +135,7 @@ describe('relationship-patterns', () => {
const error = Errors.query('Connection failed', 'pattern query', new Error('Network error'));
mockExecuteGremlinQuery.mockReturnValue(Effect.fail(error));
- const result = await Effect.runPromiseExit(generateRelationshipPatterns(mockTraversalSource));
+ const result = await Effect.runPromiseExit(generateEdgePatterns(mockTraversalSource));
expect(result._tag).toBe('Failure');
});
@@ -151,7 +151,7 @@ describe('relationship-patterns', () => {
mockExecuteGremlinQuery.mockReturnValue(Effect.succeed(mockRawPatterns));
- const result = await Effect.runPromise(generateRelationshipPatterns(mockTraversalSource));
+ const result = await Effect.runPromise(generateEdgePatterns(mockTraversalSource));
expect(result).toHaveLength(5);
@@ -173,7 +173,7 @@ describe('relationship-patterns', () => {
describe('analyzePatternStatistics', () => {
it('should analyze basic pattern statistics', () => {
- const patterns: RelationshipPattern[] = [
+ const patterns: EdgePattern[] = [
{ left_vertex: 'person', right_vertex: 'company', relation: 'worksAt' },
{ left_vertex: 'person', right_vertex: 'person', relation: 'knows' },
{ left_vertex: 'company', right_vertex: 'project', relation: 'sponsors' },
@@ -190,7 +190,7 @@ describe('relationship-patterns', () => {
});
it('should handle empty patterns array', () => {
- const patterns: RelationshipPattern[] = [];
+ const patterns: EdgePattern[] = [];
const stats = analyzePatternStatistics(patterns);
@@ -203,7 +203,7 @@ describe('relationship-patterns', () => {
});
it('should count connection frequencies correctly', () => {
- const patterns: RelationshipPattern[] = [
+ const patterns: EdgePattern[] = [
{ left_vertex: 'person', right_vertex: 'company', relation: 'worksAt' },
{ left_vertex: 'person', right_vertex: 'company', relation: 'contractsWith' },
{ left_vertex: 'person', right_vertex: 'person', relation: 'knows' },
@@ -218,7 +218,7 @@ describe('relationship-patterns', () => {
});
it('should handle duplicate patterns correctly', () => {
- const patterns: RelationshipPattern[] = [
+ const patterns: EdgePattern[] = [
{ left_vertex: 'person', right_vertex: 'company', relation: 'worksAt' },
{ left_vertex: 'person', right_vertex: 'company', relation: 'worksAt' }, // Duplicate
{ left_vertex: 'person', right_vertex: 'company', relation: 'contractsWith' },
@@ -233,7 +233,7 @@ describe('relationship-patterns', () => {
});
it('should calculate averages correctly for complex patterns', () => {
- const patterns: RelationshipPattern[] = [
+ const patterns: EdgePattern[] = [
{ left_vertex: 'person', right_vertex: 'company', relation: 'worksAt' },
{ left_vertex: 'person', right_vertex: 'project', relation: 'owns' },
{ left_vertex: 'person', right_vertex: 'person', relation: 'knows' },
@@ -251,7 +251,7 @@ describe('relationship-patterns', () => {
});
it('should sort vertex and edge types alphabetically', () => {
- const patterns: RelationshipPattern[] = [
+ const patterns: EdgePattern[] = [
{ left_vertex: 'zebra', right_vertex: 'apple', relation: 'eats' },
{ left_vertex: 'banana', right_vertex: 'cherry', relation: 'grows' },
{ left_vertex: 'apple', right_vertex: 'banana', relation: 'becomes' },
diff --git a/gremlin-tools/gremlin-mcp/tests/integration/mcp-integration.test.ts b/gremlin-tools/gremlin-mcp/tests/integration/mcp-integration.test.ts
index 5bee436780..559fff8cec 100644
--- a/gremlin-tools/gremlin-mcp/tests/integration/mcp-integration.test.ts
+++ b/gremlin-tools/gremlin-mcp/tests/integration/mcp-integration.test.ts
@@ -170,19 +170,19 @@ describe('MCP Server Integration Tests', () => {
expect(schema).toBeDefined();
expect(schema.vertices).toBeDefined();
- expect(schema.relationships).toBeDefined();
+ expect(schema.edges).toBeDefined();
expect(Array.isArray(schema.vertices)).toBe(true);
- expect(Array.isArray(schema.relationships)).toBe(true);
+ expect(Array.isArray(schema.edges)).toBe(true);
- // Verify relationship_patterns is present and adjacency_list is removed
- expect(schema.relationship_patterns).toBeDefined();
- expect(Array.isArray(schema.relationship_patterns)).toBe(true);
+ // Verify edge_patterns is present and adjacency_list is removed
+ expect(schema.edge_patterns).toBeDefined();
+ expect(Array.isArray(schema.edge_patterns)).toBe(true);
expect(schema.adjacency_list).toBeUndefined();
// Verify metadata structure
if (schema.metadata) {
expect(schema.metadata.vertex_count).toBeGreaterThanOrEqual(0);
- expect(schema.metadata.relationship_count).toBeGreaterThanOrEqual(0);
+ expect(schema.metadata.edge_count).toBeGreaterThanOrEqual(0);
expect(schema.metadata.optimization_settings).toBeDefined();
}
},
diff --git a/gremlin-tools/gremlin-mcp/tests/models.test.ts b/gremlin-tools/gremlin-mcp/tests/models.test.ts
index 3ac4550526..efa0cc15c0 100644
--- a/gremlin-tools/gremlin-mcp/tests/models.test.ts
+++ b/gremlin-tools/gremlin-mcp/tests/models.test.ts
@@ -25,7 +25,7 @@
import {
PropertySchema,
VertexSchema,
- RelationshipSchema,
+ EdgeSchema,
GraphSchemaSchema,
GremlinConfigSchema,
GremlinQueryResultSchema,
@@ -73,20 +73,20 @@ describe('Models and Schemas', () => {
});
});
- describe('RelationshipSchema', () => {
- it('should validate a valid relationship', () => {
- const validRelationship = {
+ describe('EdgeSchema', () => {
+ it('should validate a valid edge', () => {
+ const validEdge = {
type: 'knows',
properties: [],
count: 50,
};
- expect(() => RelationshipSchema.parse(validRelationship)).not.toThrow();
+ expect(() => EdgeSchema.parse(validEdge)).not.toThrow();
});
});
describe('GraphSchemaSchema', () => {
- it('should validate a complete graph schema with relationship_patterns', () => {
+ it('should validate a complete graph schema with edge_patterns', () => {
const validSchema = {
vertices: [
{
@@ -100,13 +100,13 @@ describe('Models and Schemas', () => {
],
},
],
- relationships: [
+ edges: [
{
type: 'knows',
properties: [],
},
],
- relationship_patterns: [
+ edge_patterns: [
{
left_vertex: 'person',
right_vertex: 'person',
@@ -115,7 +115,7 @@ describe('Models and Schemas', () => {
],
metadata: {
vertex_count: 1,
- relationship_count: 1,
+ edge_count: 1,
pattern_count: 1,
schema_size_bytes: 1024,
optimization_settings: {
@@ -130,9 +130,9 @@ describe('Models and Schemas', () => {
expect(() => GraphSchemaSchema.parse(validSchema)).not.toThrow();
- // Verify relationship_patterns is present and adjacency_list is not
+ // Verify edge_patterns is present and adjacency_list is not
const parsed = GraphSchemaSchema.parse(validSchema);
- expect('relationship_patterns' in parsed).toBe(true);
+ expect('edge_patterns' in parsed).toBe(true);
expect('adjacency_list' in parsed).toBe(false);
});
});
@@ -178,7 +178,7 @@ describe('Models and Schemas', () => {
it('should validate schema metadata', () => {
const validMetadata = {
vertex_count: 10,
- relationship_count: 5,
+ edge_count: 5,
pattern_count: 8,
schema_size_bytes: 2048,
optimization_settings: {
diff --git a/gremlin-tools/gremlin-mcp/tests/schema-assembly.test.ts b/gremlin-tools/gremlin-mcp/tests/schema-assembly.test.ts
index 1fb06b0147..96975209b3 100644
--- a/gremlin-tools/gremlin-mcp/tests/schema-assembly.test.ts
+++ b/gremlin-tools/gremlin-mcp/tests/schema-assembly.test.ts
@@ -30,11 +30,11 @@ import { describe, it, expect, beforeEach, jest } from '@jest/globals';
import {
assembleGraphSchema,
validateVertices,
- validateRelationships,
- validateRelationshipPatterns,
+ validateEdges,
+ validateEdgePatterns,
validateAllComponents,
} from '../src/gremlin/schema-assembly.js';
-import type { Vertex, Relationship, RelationshipPattern } from '../src/gremlin/models.js';
+import type { Vertex, Edge, EdgePattern } from '../src/gremlin/models.js';
import type { SchemaConfig } from '../src/gremlin/types.js';
describe('schema-assembly', () => {
@@ -65,7 +65,7 @@ describe('schema-assembly', () => {
},
];
- const sampleRelationships: Relationship[] = [
+ const sampleEdges: Edge[] = [
{
type: 'worksAt',
properties: [
@@ -79,7 +79,7 @@ describe('schema-assembly', () => {
},
];
- const samplePatterns: RelationshipPattern[] = [
+ const samplePatterns: EdgePattern[] = [
{ left_vertex: 'person', right_vertex: 'company', relation: 'worksAt' },
{ left_vertex: 'person', right_vertex: 'person', relation: 'knows' },
];
@@ -93,18 +93,18 @@ describe('schema-assembly', () => {
const startTime = Date.now();
const result = await Effect.runPromise(
- assembleGraphSchema(sampleVertices, sampleRelationships, samplePatterns, mockConfig, startTime)
+ assembleGraphSchema(sampleVertices, sampleEdges, samplePatterns, mockConfig, startTime)
);
// Verify schema structure
expect(result.vertices).toEqual(sampleVertices);
- expect(result.relationships).toEqual(sampleRelationships);
- expect(result.relationship_patterns).toEqual(samplePatterns);
+ expect(result.edges).toEqual(sampleEdges);
+ expect(result.edge_patterns).toEqual(samplePatterns);
// Verify metadata
expect(result.metadata).toBeDefined();
expect(result.metadata!.vertex_count).toBe(2);
- expect(result.metadata!.relationship_count).toBe(2);
+ expect(result.metadata!.edge_count).toBe(2);
expect(result.metadata!.pattern_count).toBe(2);
expect(result.metadata!.generated_at).toBeDefined();
expect(result.metadata!.generation_time_ms).toBeGreaterThanOrEqual(0);
@@ -128,10 +128,10 @@ describe('schema-assembly', () => {
);
expect(result.vertices).toEqual([]);
- expect(result.relationships).toEqual([]);
- expect(result.relationship_patterns).toEqual([]);
+ expect(result.edges).toEqual([]);
+ expect(result.edge_patterns).toEqual([]);
expect(result.metadata!.vertex_count).toBe(0);
- expect(result.metadata!.relationship_count).toBe(0);
+ expect(result.metadata!.edge_count).toBe(0);
expect(result.metadata!.pattern_count).toBe(0);
});
@@ -139,7 +139,7 @@ describe('schema-assembly', () => {
const startTime = Date.now() - 1000; // 1 second ago
const result = await Effect.runPromise(
- assembleGraphSchema(sampleVertices, sampleRelationships, samplePatterns, mockConfig, startTime)
+ assembleGraphSchema(sampleVertices, sampleEdges, samplePatterns, mockConfig, startTime)
);
expect(result.metadata!.generation_time_ms).toBeGreaterThanOrEqual(1000);
@@ -157,7 +157,7 @@ describe('schema-assembly', () => {
const result = await Effect.runPromiseExit(
assembleGraphSchema(
invalidVertices,
- sampleRelationships,
+ sampleEdges,
samplePatterns,
mockConfig,
Date.now()
@@ -234,28 +234,28 @@ describe('schema-assembly', () => {
});
});
- describe('validateRelationships', () => {
+ describe('validateEdges', () => {
it('should validate correct relationships successfully', async () => {
- const result = await Effect.runPromise(validateRelationships(sampleRelationships));
+ const result = await Effect.runPromise(validateEdges(sampleEdges));
expect(result).toBeUndefined(); // Void return on success
});
it('should detect missing labels', async () => {
- const invalidRelationships: Relationship[] = [
+ const invalidEdges: Edge[] = [
{
type: '', // Invalid empty type
properties: [],
},
];
- const result = await Effect.runPromiseExit(validateRelationships(invalidRelationships));
+ const result = await Effect.runPromiseExit(validateEdges(invalidEdges));
expect(result._tag).toBe('Failure');
});
it('should detect invalid properties', async () => {
- const invalidRelationships: Relationship[] = [
+ const invalidEdges: Edge[] = [
{
type: 'knows',
properties: [
@@ -264,34 +264,34 @@ describe('schema-assembly', () => {
},
];
- const result = await Effect.runPromiseExit(validateRelationships(invalidRelationships));
+ const result = await Effect.runPromiseExit(validateEdges(invalidEdges));
expect(result._tag).toBe('Failure');
});
it('should handle missing properties array', async () => {
- const invalidRelationships: Relationship[] = [
+ const invalidEdges: Edge[] = [
{
type: 'knows',
properties: undefined as any, // Missing properties
},
];
- const result = await Effect.runPromiseExit(validateRelationships(invalidRelationships));
+ const result = await Effect.runPromiseExit(validateEdges(invalidEdges));
expect(result._tag).toBe('Failure');
});
});
- describe('validateRelationshipPatterns', () => {
+ describe('validateEdgePatterns', () => {
it('should validate correct patterns successfully', async () => {
- const result = await Effect.runPromise(validateRelationshipPatterns(samplePatterns));
+ const result = await Effect.runPromise(validateEdgePatterns(samplePatterns));
expect(result).toBeUndefined(); // Void return on success
});
it('should detect missing pattern fields', async () => {
- const invalidPatterns: RelationshipPattern[] = [
+ const invalidPatterns: EdgePattern[] = [
{
left_vertex: '', // Empty left vertex
right_vertex: 'company',
@@ -309,13 +309,13 @@ describe('schema-assembly', () => {
},
];
- const result = await Effect.runPromiseExit(validateRelationshipPatterns(invalidPatterns));
+ const result = await Effect.runPromiseExit(validateEdgePatterns(invalidPatterns));
expect(result._tag).toBe('Failure');
});
it('should detect invalid pattern field types', async () => {
- const invalidPatterns: RelationshipPattern[] = [
+ const invalidPatterns: EdgePattern[] = [
{
left_vertex: null as any, // Invalid type
right_vertex: 'company',
@@ -323,7 +323,7 @@ describe('schema-assembly', () => {
},
];
- const result = await Effect.runPromiseExit(validateRelationshipPatterns(invalidPatterns));
+ const result = await Effect.runPromiseExit(validateEdgePatterns(invalidPatterns));
expect(result._tag).toBe('Failure');
});
@@ -332,7 +332,7 @@ describe('schema-assembly', () => {
describe('validateAllComponents', () => {
it('should validate all components successfully', async () => {
const result = await Effect.runPromise(
- validateAllComponents(sampleVertices, sampleRelationships, samplePatterns)
+ validateAllComponents(sampleVertices, sampleEdges, samplePatterns)
);
expect(result).toBeUndefined(); // Void return on success
@@ -347,15 +347,15 @@ describe('schema-assembly', () => {
];
const result = await Effect.runPromiseExit(
- validateAllComponents(invalidVertices, sampleRelationships, samplePatterns)
+ validateAllComponents(invalidVertices, sampleEdges, samplePatterns)
);
expect(result._tag).toBe('Failure');
});
it('should validate each component type independently', async () => {
- // Test with valid vertices but invalid relationships
- const invalidRelationships: Relationship[] = [
+ // Test with valid vertices but invalid edges
+ const invalidEdges: Edge[] = [
{
type: '', // Invalid
properties: [],
@@ -363,7 +363,7 @@ describe('schema-assembly', () => {
];
const result = await Effect.runPromiseExit(
- validateAllComponents(sampleVertices, invalidRelationships, samplePatterns)
+ validateAllComponents(sampleVertices, invalidEdges, samplePatterns)
);
expect(result._tag).toBe('Failure');
@@ -375,7 +375,7 @@ describe('schema-assembly', () => {
const startTime = Date.now() - 500;
const result = await Effect.runPromise(
- assembleGraphSchema(sampleVertices, sampleRelationships, samplePatterns, mockConfig, startTime)
+ assembleGraphSchema(sampleVertices, sampleEdges, samplePatterns, mockConfig, startTime)
);
const metadata = result.metadata!;
@@ -384,7 +384,7 @@ describe('schema-assembly', () => {
expect(metadata.generated_at).toMatch(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/); // ISO format
expect(metadata.generation_time_ms).toBeGreaterThanOrEqual(500);
expect(metadata.vertex_count).toBe(sampleVertices.length);
- expect(metadata.relationship_count).toBe(sampleRelationships.length);
+ expect(metadata.edge_count).toBe(sampleEdges.length);
expect(metadata.pattern_count).toBe(samplePatterns.length);
// Check optimization settings
@@ -410,7 +410,7 @@ describe('schema-assembly', () => {
const result = await Effect.runPromise(
assembleGraphSchema(
sampleVertices,
- sampleRelationships,
+ sampleEdges,
samplePatterns,
minimalConfig,
Date.now()