Skip to content

Commit 4e99e77

Browse files
authored
feat: gremlin.js browser support (#2506)
- Replace node APIs that have cross runtime equivalent - For those that can't be replaced, use `node:` prefix so that environment that does polyfill automatically can easily do so - Remove manual ping/pong logic, this is already handled internally by browser or `ws` library
1 parent a0919dc commit 4e99e77

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

63 files changed

+2196
-179
lines changed
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# Logs
2+
logs
3+
*.log
4+
npm-debug.log*
5+
yarn-debug.log*
6+
yarn-error.log*
7+
pnpm-debug.log*
8+
lerna-debug.log*
9+
10+
node_modules
11+
dist
12+
dist-ssr
13+
*.local
14+
15+
.pnp.*
16+
.yarn/*
17+
!.yarn/patches
18+
!.yarn/plugins
19+
!.yarn/releases
20+
!.yarn/sdks
21+
!.yarn/versions
22+
23+
# Editor directories and files
24+
.vscode/*
25+
!.vscode/extensions.json
26+
.idea
27+
.DS_Store
28+
*.suo
29+
*.ntvs*
30+
*.njsproj
31+
*.sln
32+
*.sw?
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
nodeLinker: node-modules
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
body {
21+
margin: 0;
22+
background-color: rgb(27, 30, 34);
23+
background-image: radial-gradient(rgb(51, 64, 76) 1px, transparent 0);
24+
background-size: 35px 35px;
25+
}
26+
27+
#graph {
28+
min-width: 100dvw;
29+
min-height: 100dvh;
30+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<!--
2+
Licensed to the Apache Software Foundation (ASF) under one
3+
or more contributor license agreements. See the NOTICE file
4+
distributed with this work for additional information
5+
regarding copyright ownership. The ASF licenses this file
6+
to you under the Apache License, Version 2.0 (the
7+
"License"); you may not use this file except in compliance
8+
with the License. You may obtain a copy of the License at
9+
10+
http://www.apache.org/licenses/LICENSE-2.0
11+
12+
Unless required by applicable law or agreed to in writing,
13+
software distributed under the License is distributed on an
14+
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
KIND, either express or implied. See the License for the
16+
specific language governing permissions and limitations
17+
under the License.
18+
-->
19+
20+
<!DOCTYPE html>
21+
<html lang="en">
22+
<head>
23+
<meta charset="UTF-8" />
24+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
25+
<title>Gremlin JavaScript</title>
26+
<link rel="stylesheet" href="index.css" />
27+
</head>
28+
<body>
29+
<main id="graph"></main>
30+
<script type="module" src="index.js"></script>
31+
</body>
32+
</html>
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
import Color from "colorjs.io";
21+
import cytoscape from "cytoscape";
22+
import gremlin from "gremlin";
23+
import { createRandomColorGenerator } from "./utils";
24+
25+
const randomColor = createRandomColorGenerator();
26+
27+
const g = gremlin.process.AnonymousTraversalSource.traversal().withRemote(
28+
new gremlin.driver.DriverRemoteConnection("ws://localhost:8182/gremlin")
29+
);
30+
31+
const [vertices, edges] = await Promise.all([
32+
await g.V().toList(),
33+
await g.E().toList(),
34+
]);
35+
36+
cytoscape({
37+
container: globalThis.document.getElementById("graph"),
38+
elements: [
39+
...vertices.map((vertex) => ({
40+
data: {
41+
id: vertex.id,
42+
},
43+
style: {
44+
label: `${vertex.label}\n${vertex.id}`,
45+
"background-color": randomColor(vertex.label),
46+
"border-color": new Color(randomColor(vertex.label)).darken().toString({
47+
format: "hex",
48+
}),
49+
},
50+
})),
51+
...edges.map((edge) => ({
52+
data: {
53+
id: edge.id,
54+
label: edge.label,
55+
source: edge.inV.id,
56+
target: edge.outV.id,
57+
},
58+
})),
59+
],
60+
style: [
61+
{
62+
selector: "node",
63+
style: {
64+
color: "white",
65+
"text-valign": "center",
66+
"text-halign": "center",
67+
"border-width": 4,
68+
width: "80px",
69+
height: "80px",
70+
"text-max-width": "80px",
71+
"text-wrap": "wrap",
72+
},
73+
},
74+
75+
{
76+
selector: "edge",
77+
style: {
78+
label: "data(label)",
79+
color: "white",
80+
"text-outline-color": "black",
81+
"text-outline-width": "2px",
82+
"text-margin-y": "-6px",
83+
"text-rotation": "autorotate",
84+
"target-arrow-shape": "triangle",
85+
"curve-style": "bezier",
86+
},
87+
},
88+
],
89+
layout: {
90+
name: "cose",
91+
},
92+
});
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
{
2+
"name": "browser",
3+
"version": "0.0.0",
4+
"description": "GLV example for JavaScript in the browser",
5+
"author": "Apache TinkerPop team",
6+
"license": "Apache-2.0",
7+
"type": "module",
8+
"packageManager": "[email protected]",
9+
"scripts": {
10+
"dev": "vite",
11+
"build": "vite build",
12+
"preview": "vite preview"
13+
},
14+
"dependencies": {
15+
"colorjs.io": "^0.5.0",
16+
"cytoscape": "^3.28.1",
17+
"gremlin": "file:../../src/main/javascript/gremlin-javascript"
18+
},
19+
"devDependencies": {
20+
"vite": "^5.1.4"
21+
}
22+
}
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
function shuffle(array) {
21+
const length = array == null ? 0 : array.length;
22+
if (!length) {
23+
return [];
24+
}
25+
let index = -1;
26+
const lastIndex = length - 1;
27+
while (++index < length) {
28+
const rand = index + Math.floor(Math.random() * (lastIndex - index + 1));
29+
const value = array[rand];
30+
array[rand] = array[index];
31+
array[index] = value;
32+
}
33+
return array;
34+
}
35+
36+
export const createRandomColorGenerator = () => {
37+
const colors = [
38+
"#C62828",
39+
"#AD1457",
40+
"#6A1B9A",
41+
"#4527A0",
42+
"#283593",
43+
"#1565C0",
44+
"#0277BD",
45+
"#00838F",
46+
"#00695C",
47+
"#2E7D32",
48+
"#558B2F",
49+
"#9E9D24",
50+
"#F9A825",
51+
"#FF8F00",
52+
"#EF6C00",
53+
"#D84315",
54+
"#4E342E",
55+
"#424242",
56+
"#37474F",
57+
];
58+
59+
const colorMap = new Map();
60+
61+
return (key) => {
62+
const storedColor = colorMap.get(key);
63+
64+
if (storedColor !== undefined) {
65+
return storedColor;
66+
}
67+
68+
const color = shuffle(colors).pop();
69+
70+
colorMap.set(key, color);
71+
72+
return color;
73+
};
74+
};

0 commit comments

Comments
 (0)