Skip to content

Commit 77ca34f

Browse files
authored
Fix parsing of Gremlin map (#1498)
1 parent 73e757f commit 77ca34f

File tree

2 files changed

+87
-9
lines changed

2 files changed

+87
-9
lines changed

packages/graph-explorer/src/connector/gremlin/fetchEdgeConnections/index.test.ts

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,82 @@ describe("Gremlin > fetchEdgeConnections", () => {
172172
],
173173
});
174174
});
175+
176+
it("should handle reversed key order in GraphSON map", async () => {
177+
const reversedKeyOrderResponse = {
178+
requestId: "test-request-id",
179+
status: { message: "", code: 200 },
180+
result: {
181+
data: {
182+
"@type": "g:List",
183+
"@value": [
184+
{
185+
"@type": "g:Map",
186+
"@value": ["targetType", "airport", "sourceType", "country"],
187+
},
188+
],
189+
},
190+
},
191+
};
192+
const gremlinFetch = vi
193+
.fn()
194+
.mockResolvedValueOnce(reversedKeyOrderResponse);
195+
196+
const result = await fetchEdgeConnections(gremlinFetch, {
197+
edgeTypes: [createEdgeType("contains")],
198+
});
199+
200+
expect(result).toStrictEqual({
201+
edgeConnections: [
202+
{
203+
sourceVertexType: createVertexType("country"),
204+
edgeType: createEdgeType("contains"),
205+
targetVertexType: createVertexType("airport"),
206+
},
207+
],
208+
});
209+
});
210+
211+
it("should skip entries with missing sourceType or targetType", async () => {
212+
const missingKeysResponse = {
213+
requestId: "test-request-id",
214+
status: { message: "", code: 200 },
215+
result: {
216+
data: {
217+
"@type": "g:List",
218+
"@value": [
219+
{
220+
"@type": "g:Map",
221+
"@value": ["sourceType", "airport"],
222+
},
223+
{
224+
"@type": "g:Map",
225+
"@value": ["targetType", "airport"],
226+
},
227+
{
228+
"@type": "g:Map",
229+
"@value": ["sourceType", "country", "targetType", "airport"],
230+
},
231+
],
232+
},
233+
},
234+
};
235+
const gremlinFetch = vi.fn().mockResolvedValueOnce(missingKeysResponse);
236+
237+
const result = await fetchEdgeConnections(gremlinFetch, {
238+
edgeTypes: [createEdgeType("contains")],
239+
});
240+
241+
expect(result).toStrictEqual({
242+
edgeConnections: [
243+
{
244+
sourceVertexType: createVertexType("country"),
245+
edgeType: createEdgeType("contains"),
246+
targetVertexType: createVertexType("airport"),
247+
},
248+
],
249+
});
250+
});
175251
});
176252

177253
const routeResponse = {

packages/graph-explorer/src/connector/gremlin/fetchEdgeConnections/index.ts

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,11 @@ import { createEdgeType, createVertexType, type EdgeConnection } from "@/core";
77
import batchPromisesSerially from "@/utils/batchPromisesSerially";
88
import { DEFAULT_CONCURRENT_REQUESTS_LIMIT } from "@/utils/constants";
99

10-
import type { GremlinFetch } from "../types";
10+
import type { GMapWithValue, GremlinFetch } from "../types";
1111

12+
import { parseGMap } from "../mappers/parseGMap";
1213
import edgeConnectionsTemplate from "./edgeConnectionsTemplate";
1314

14-
type GEdgeConnectionValue = {
15-
"@type": "g:Map";
16-
"@value": Array<string>;
17-
};
18-
1915
type RawEdgeConnectionsResponse = {
2016
requestId: string;
2117
status: {
@@ -25,7 +21,7 @@ type RawEdgeConnectionsResponse = {
2521
result: {
2622
data: {
2723
"@type": "g:List";
28-
"@value": Array<GEdgeConnectionValue>;
24+
"@value": Array<GMapWithValue<string, string>>;
2925
};
3026
};
3127
};
@@ -49,8 +45,14 @@ export default async function fetchEdgeConnections(
4945

5046
for (const { edgeType, values } of results) {
5147
for (const item of values) {
52-
// Map format: ['sourceType', value, 'targetType', value]
53-
const [, sourceValue, , targetValue] = item["@value"];
48+
const map = parseGMap(item);
49+
const sourceValue = map.get("sourceType");
50+
const targetValue = map.get("targetType");
51+
52+
if (!sourceValue || !targetValue) {
53+
continue;
54+
}
55+
5456
// Neptune multi-label vertices use :: delimiter
5557
const sourceTypes = sourceValue.split("::").filter(Boolean);
5658
const targetTypes = targetValue.split("::").filter(Boolean);

0 commit comments

Comments
 (0)