diff --git a/magic-api-plugins/magic-api-plugin-nebula/nebula插件.md b/magic-api-plugins/magic-api-plugin-nebula/nebula插件.md
new file mode 100644
index 00000000..62317085
--- /dev/null
+++ b/magic-api-plugins/magic-api-plugin-nebula/nebula插件.md
@@ -0,0 +1,99 @@
+---
+title: nebula插件
+date: 2023-08-16 09:16:55
+---
+
+### 引入依赖
+
+```xml
+
+
+ org.ssssssss
+ magic-api-plugin-nebula
+ magic-api-lastest-version
+
+```
+
+### 配置
+
+```yml
+nebula:
+ hostAddress: ${NEBULA_HOSTADDRESS:localhost:9669}
+ userName: ${NEBULA_USERNAME:root}
+ password: ${NEBULA_PASSWORD:nebula}
+
+```
+
+### 使用
+
+```js
+import nebula;
+var ngsl =
+ """"
+ USE db_name;MATCH p_=(p:`assignee`)-[*3]-(p2:`transferor`) where id(p2) == "阿里巴巴" or id(p)== "阿里巴巴" RETURN p_ limit 1000'
+ """
+var resultJson = nebula.executeJson(ngsl)
+nebula.convert(resultJson)
+
+
+nebula.executeNebulaModel(ngsl)
+
+其他支持的方法不太常用, 这里不再一一列举, 可参考源码
+org.ssssssss.magicapi.nebula.NebulaModule
+```
+
+#### 返回的数据格式为:
+```
+ 该结构的数据可被很多前端组件库支持进行可视化展示
+```
+如: [angv G6](http://antv-2018.alipay.com/zh-cn/g6/3.x/demo/index.html)
+
+
+```json
+{
+ "code": 0,
+ "message": "success",
+ "data": {
+ "nodes": [
+ {
+ "edgeSize": 1,
+ "assignee.name": "中航纽赫融资租赁(上海)有限公司",
+ "type": "vertex",
+ "assignee.addr": "上海市中国(上海)自由贸易试验区正定路530号A5库区集中辅助区三层318室",
+ "assignee.legal_person": "周勇",
+ "registrant.addr": "上海市浦东新区南泉路1261号",
+ "registrant.name": "中航国际租赁有限公司",
+ "id": "中航纽赫融资租赁(上海)有限公司",
+ "assignee.type": "企业"
+ },
+ {
+ "edgeSize": 15,
+ "type": "vertex",
+ "transferor.name": "陕西海富融资租赁有限公司",
+ "transferor.legal_person": "刘子瑜",
+ "transferor.type": "企业",
+ "transferor.addr": "陕西省西安市西安经济技术开发区未央路170号赛高城市广场2号楼企业总部大厦26层05单元",
+ "registrant.addr": "广东省深圳市前海深港合作区南山街道梦海大厦5035号前海华润金融中心T5写字楼1808",
+ "registrant.name": "深圳前海盈峰商业保理有限公司",
+ "id": "陕西海富融资租赁有限公司"
+ }, ...
+ ],
+ "edges": [
+ {
+ "dst": "陕西海富融资租赁有限公司",
+ "src": "中航纽赫融资租赁(上海)有限公司",
+ "source": "中航纽赫融资租赁(上海)有限公司",
+ "label": "trans_with",
+ "type": "edge",
+ "target": "陕西海富融资租赁有限公司",
+ "name": "trans_with",
+ "ranking": 0,
+ "value": 0
+ },...
+ ]
+ },
+ "timestamp": 1692149280167,
+ "requestTime": 1692149280143,
+ "executeTime": 24
+}
+```
\ No newline at end of file
diff --git a/magic-api-plugins/magic-api-plugin-nebula/pom.xml b/magic-api-plugins/magic-api-plugin-nebula/pom.xml
new file mode 100644
index 00000000..43e906d0
--- /dev/null
+++ b/magic-api-plugins/magic-api-plugin-nebula/pom.xml
@@ -0,0 +1,33 @@
+
+ 4.0.0
+
+ org.ssssssss
+ magic-api-plugins
+ 2.1.1
+
+
+ magic-api-plugin-nebula
+ jar
+
+ magic-api-plugin-nebula
+
+
+ UTF-8
+ 3.5.0
+
+
+
+
+ com.vesoft
+ client
+ ${vesoft.version}
+
+
+ guava
+ com.google.guava
+
+
+
+
+
diff --git a/magic-api-plugins/magic-api-plugin-nebula/src/main/java/org/ssssssss/magicapi/nebula/MagicNebulaConfiguration.java b/magic-api-plugins/magic-api-plugin-nebula/src/main/java/org/ssssssss/magicapi/nebula/MagicNebulaConfiguration.java
new file mode 100644
index 00000000..6837fb39
--- /dev/null
+++ b/magic-api-plugins/magic-api-plugin-nebula/src/main/java/org/ssssssss/magicapi/nebula/MagicNebulaConfiguration.java
@@ -0,0 +1,104 @@
+package org.ssssssss.magicapi.nebula;
+
+
+import com.vesoft.nebula.client.graph.NebulaPoolConfig;
+import com.vesoft.nebula.client.graph.data.HostAddress;
+import com.vesoft.nebula.client.graph.net.NebulaPool;
+import com.vesoft.nebula.client.graph.net.Session;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.ssssssss.magicapi.core.config.MagicAPIProperties;
+import org.ssssssss.magicapi.core.config.MagicPluginConfiguration;
+import org.ssssssss.magicapi.core.model.Plugin;
+import org.ssssssss.magicapi.utils.Assert;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
+/**
+ * Nebula自动配置类
+ */
+
+@Configuration
+@EnableConfigurationProperties(NebulaPoolProperties.class)
+public class MagicNebulaConfiguration implements MagicPluginConfiguration {
+ private static final Logger logger = LoggerFactory.getLogger(MagicNebulaConfiguration.class);
+
+ private NebulaPoolProperties nebulaPoolProperties;
+
+ private final MagicAPIProperties properties;
+
+ public MagicNebulaConfiguration(MagicAPIProperties properties, NebulaPoolProperties nebulaPoolProperties) {
+ this.properties = properties;
+ this.nebulaPoolProperties = nebulaPoolProperties;
+ }
+
+ /**
+ * 创建nebula pool
+ * @param nebulaPoolProperties
+ * @return
+ */
+ @Bean
+ public NebulaPool nebulaPool(@Autowired NebulaPoolProperties nebulaPoolProperties) {
+ Session session = null;
+ try {
+
+ NebulaPoolConfig nebulaPoolConfig = buildNebulaPoolConfig(nebulaPoolProperties);
+ Assert.isNotBlank(nebulaPoolProperties.getHostAddress(), "nebula.hostAddress 不能为空, 格式为 ip:port,ip:port 配置多个地址用逗号分隔");
+ String[] hostAddress = nebulaPoolProperties.getHostAddress().split(",");
+ List addresses = Arrays.stream(hostAddress).map(address -> {
+ String[] ipAndPort = address.split(":");
+ Assert.isTrue(ipAndPort.length == 2, "nebula.hostAddress 格式错误, 格式为 ip:port,ip:port 配置多个地址用逗号分隔");
+ return new HostAddress(ipAndPort[0], Integer.parseInt(ipAndPort[1]));
+ }).collect(Collectors.toList());
+
+ NebulaPool pool = new NebulaPool();
+ pool.init(addresses, nebulaPoolConfig);
+ session = pool.getSession(nebulaPoolProperties.getUserName(), nebulaPoolProperties.getPassword(), nebulaPoolProperties.isReconnect());
+ return pool;
+ } catch (Exception e) {
+ logger.error("初始化nebula pool 异常", e);
+ throw new RuntimeException(e);
+ } finally {
+ logger.info("初始化nebula pool 完成");
+ Optional.ofNullable(session).ifPresent(Session::release);
+ }
+ }
+
+ /**
+ * 注入模块
+ * @return
+ */
+ @Bean
+ public NebulaModule nebulaModule() {
+ return new NebulaModule();
+ }
+
+ @Override
+ public Plugin plugin() {
+ return new Plugin("Nebula");
+ }
+
+
+ public NebulaPoolConfig buildNebulaPoolConfig(NebulaPoolProperties nebulaPoolProperties) {
+
+ NebulaPoolConfig nebulaPoolConfig = new NebulaPoolConfig();
+ //将nebulaPoolProperties的同名属性赋值到nebulaPoolConfig
+ nebulaPoolConfig.setMinConnSize(nebulaPoolProperties.getMinConnsSize());
+ nebulaPoolConfig.setSslParam(nebulaPoolProperties.getSslParam());
+ nebulaPoolConfig.setWaitTime(nebulaPoolProperties.getWaitTime());
+ nebulaPoolConfig.setTimeout(nebulaPoolProperties.getTimeout());
+ nebulaPoolConfig.setMaxConnSize(nebulaPoolProperties.getMaxConnsSize());
+ nebulaPoolConfig.setIntervalIdle(nebulaPoolProperties.getIntervalIdle());
+ nebulaPoolConfig.setMinClusterHealthRate(nebulaPoolProperties.getMinClusterHealthRate());
+ nebulaPoolConfig.setIdleTime(nebulaPoolProperties.getIdleTime());
+ nebulaPoolConfig.setEnableSsl(nebulaPoolProperties.isEnableSsl());
+ return nebulaPoolConfig;
+ }
+}
diff --git a/magic-api-plugins/magic-api-plugin-nebula/src/main/java/org/ssssssss/magicapi/nebula/NebulaModule.java b/magic-api-plugins/magic-api-plugin-nebula/src/main/java/org/ssssssss/magicapi/nebula/NebulaModule.java
new file mode 100644
index 00000000..4d3aa3fa
--- /dev/null
+++ b/magic-api-plugins/magic-api-plugin-nebula/src/main/java/org/ssssssss/magicapi/nebula/NebulaModule.java
@@ -0,0 +1,157 @@
+package org.ssssssss.magicapi.nebula;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.vesoft.nebula.client.graph.data.ResultSet;
+import com.vesoft.nebula.client.graph.net.NebulaPool;
+import com.vesoft.nebula.client.graph.net.Session;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.NoSuchBeanDefinitionException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.ssssssss.magicapi.core.annotation.MagicModule;
+import org.ssssssss.magicapi.nebula.model.Edge;
+import org.ssssssss.magicapi.nebula.model.NebulaModel;
+import org.ssssssss.magicapi.nebula.model.Node;
+import org.ssssssss.magicapi.nebula.response.*;
+import org.ssssssss.script.annotation.Comment;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Optional;
+
+
+@MagicModule("nebula")
+public class NebulaModule {
+
+ @Autowired
+ private NebulaPool nebulaPool;
+
+ @Autowired
+ private NebulaPoolProperties nebulaPoolProperties;
+
+ private static final Logger logger = LoggerFactory.getLogger(NebulaModule.class);
+
+
+ /**
+ * 执行ngsl脚本, 返回json格式结果
+ *
+ * @param script
+ * @return
+ */
+ @Comment("执行ngsl脚本, 返回json格式结果")
+ public Object executeJson(String script) {
+ Session session = getNebulaSession();
+ try {
+ String json = session.executeJson(script);
+ return json;
+ } catch (Exception e) {
+ logger.error("执行Nebula脚本异常, script: {}", script, e);
+ throw new RuntimeException(e);
+ } finally {
+ Optional.ofNullable(session).ifPresent(Session::release);
+ }
+ }
+
+
+ /**
+ * 执行ngsl脚本, 并解析为可视化格式
+ *
+ * @param script
+ * @return
+ */
+ @Comment("执行ngsl脚本, 返回json格式结果, 并解析为可视化格式")
+ public NebulaModel executeNebulaModel(String script) {
+ Session session = getNebulaSession();
+ try {
+ String json = session.executeJson(script);
+ return convert(json);
+ } catch (Exception e) {
+ logger.error("执行Nebula脚本异常, script: {}", script, e);
+ throw new RuntimeException(e);
+ } finally {
+ Optional.ofNullable(session).ifPresent(Session::release);
+ }
+ }
+
+
+ /**
+ * 执行ngsl脚本, 返回ResultSet格式结果, 不可直接使用
+ *
+ * @param script
+ * @return
+ */
+ @Comment("执行ngsl脚本, 返回ResultSet格式结果, 无法直接使用")
+ public Object execute(String script) {
+ Session session = getNebulaSession();
+ try {
+ ResultSet resultSet = session.execute(script);
+ return resultSet;
+ } catch (Exception e) {
+ logger.error("执行Nebula脚本异常, script: {}", script, e);
+ throw new RuntimeException(e);
+ } finally {
+ Optional.ofNullable(session).ifPresent(Session::release);
+ }
+ }
+
+ public Session getNebulaSession() {
+ try {
+ return nebulaPool.getSession(nebulaPoolProperties.getUserName(), nebulaPoolProperties.getPassword(), nebulaPoolProperties.isReconnect());
+ } catch (NoSuchBeanDefinitionException e) {
+ throw new RuntimeException(String.format("NebulaPool 未初始化, 或初始化异常, 请检查配置文件"));
+ } catch (Exception e) {
+ logger.error("获取nebula session 异常", e);
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Comment("解析nebula结果为可视化格式")
+ public NebulaModel convert(String json) throws Exception {
+ ObjectMapper objectMapper = new ObjectMapper();
+ NebulaJsonBody response = objectMapper.readValue(json, NebulaJsonBody.class);
+
+ //状态码不为0则为异常, 解析提示异常信息
+ if (response.getErrorCode() != 0) {
+ logger.error("执行Nebula脚本异常, script: {}, errorMsg: {}", json, response.getErrorMsg());
+ throw new RuntimeException(response.getErrorMsg());
+ }
+
+ NebulaModel nebulaModel = new NebulaModel();
+ HashMap nodeEdges = new HashMap<>();
+ List datas = response.getResults().get(0).getData();
+ for (int index = 0; index < datas.size(); index++) {
+ List> meta = datas.get(index).getMeta();
+ List>> row = datas.get(index).getRow();
+ for (int i = 0; i < meta.get(0).size(); i++) {
+ Element element = meta.get(0).get(i);
+ HashMap elementDetail = row.get(0).get(i);
+ Node node = new Node();
+ Edge edge = new Edge();
+
+ if (element instanceof Vertex) {
+ node.setId(((Vertex) element).getId());
+ node.getProp().putAll(elementDetail);
+ nebulaModel.addNode(node);
+
+ } else if (element instanceof EdgeElement) {
+ edge.getProp().putAll(elementDetail);
+ EdgeId id = ((EdgeElement) element).getId();
+ edge.setTarget(id.getDst());
+ edge.setSource(id.getSrc());
+ edge.setLabel(id.getName());
+ edge.setValue(id.getRanking());
+ nebulaModel.getEdges().add(edge);
+
+ nodeEdges.put(id.getDst(), nodeEdges.getOrDefault(id.getDst(), 0) + 1);
+ nodeEdges.put(id.getSrc(), nodeEdges.getOrDefault(id.getSrc(), 0) + 1);
+ }
+ }
+ // 补充节点边的数量值
+ for (Node node : nebulaModel.getNodes()) {
+ node.setEdgeSize(nodeEdges.getOrDefault(node.getId(), 0));
+ }
+ }
+ return nebulaModel;
+ }
+
+}
diff --git a/magic-api-plugins/magic-api-plugin-nebula/src/main/java/org/ssssssss/magicapi/nebula/NebulaPoolProperties.java b/magic-api-plugins/magic-api-plugin-nebula/src/main/java/org/ssssssss/magicapi/nebula/NebulaPoolProperties.java
new file mode 100644
index 00000000..7f4c28a2
--- /dev/null
+++ b/magic-api-plugins/magic-api-plugin-nebula/src/main/java/org/ssssssss/magicapi/nebula/NebulaPoolProperties.java
@@ -0,0 +1,141 @@
+package org.ssssssss.magicapi.nebula;
+
+import com.vesoft.nebula.client.graph.data.SSLParam;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+
+
+@ConfigurationProperties(prefix = "nebula")
+public class NebulaPoolProperties {
+
+ /** nebula 服务地址, 多个则逗号分割, 格式为 ip:port */
+ private String hostAddress;
+ /** nebula 用户名 */
+ private String userName;
+ /** nebula 密码 */
+ private String password;
+
+ private boolean reconnect = true;
+ /** nebula 连接池最小连接数 */
+ private int minConnsSize = 0;
+ /** nebula 连接池最大连接数 */
+ private int maxConnsSize = 10;
+ /** nebula 连接池最大等待时间 */
+ private int timeout = 0;
+ /** nebula 连接池空闲时间 */
+ private int idleTime = 0;
+ /** nebula 连接池心跳间隔 */
+ private int intervalIdle = -1;
+
+ private int waitTime = 0;
+
+ private double minClusterHealthRate = 1.0;
+
+ private boolean enableSsl = false;
+
+ private SSLParam sslParam = null;
+
+ public String getHostAddress() {
+ return hostAddress;
+ }
+
+ public void setHostAddress(String hostAddress) {
+ this.hostAddress = hostAddress;
+ }
+
+ public String getUserName() {
+ return userName;
+ }
+
+ public void setUserName(String userName) {
+ this.userName = userName;
+ }
+
+ public String getPassword() {
+ return password;
+ }
+
+ public void setPassword(String password) {
+ this.password = password;
+ }
+
+ public boolean isReconnect() {
+ return reconnect;
+ }
+
+ public void setReconnect(boolean reconnect) {
+ this.reconnect = reconnect;
+ }
+
+ public int getMinConnsSize() {
+ return minConnsSize;
+ }
+
+ public void setMinConnsSize(int minConnsSize) {
+ this.minConnsSize = minConnsSize;
+ }
+
+ public int getMaxConnsSize() {
+ return maxConnsSize;
+ }
+
+ public void setMaxConnsSize(int maxConnsSize) {
+ this.maxConnsSize = maxConnsSize;
+ }
+
+ public int getTimeout() {
+ return timeout;
+ }
+
+ public void setTimeout(int timeout) {
+ this.timeout = timeout;
+ }
+
+ public int getIdleTime() {
+ return idleTime;
+ }
+
+ public void setIdleTime(int idleTime) {
+ this.idleTime = idleTime;
+ }
+
+ public int getIntervalIdle() {
+ return intervalIdle;
+ }
+
+ public void setIntervalIdle(int intervalIdle) {
+ this.intervalIdle = intervalIdle;
+ }
+
+ public int getWaitTime() {
+ return waitTime;
+ }
+
+ public void setWaitTime(int waitTime) {
+ this.waitTime = waitTime;
+ }
+
+ public double getMinClusterHealthRate() {
+ return minClusterHealthRate;
+ }
+
+ public void setMinClusterHealthRate(double minClusterHealthRate) {
+ this.minClusterHealthRate = minClusterHealthRate;
+ }
+
+ public boolean isEnableSsl() {
+ return enableSsl;
+ }
+
+ public void setEnableSsl(boolean enableSsl) {
+ this.enableSsl = enableSsl;
+ }
+
+ public SSLParam getSslParam() {
+ return sslParam;
+ }
+
+ public void setSslParam(SSLParam sslParam) {
+ this.sslParam = sslParam;
+ }
+}
diff --git a/magic-api-plugins/magic-api-plugin-nebula/src/main/java/org/ssssssss/magicapi/nebula/model/Edge.java b/magic-api-plugins/magic-api-plugin-nebula/src/main/java/org/ssssssss/magicapi/nebula/model/Edge.java
new file mode 100644
index 00000000..8ef9b90e
--- /dev/null
+++ b/magic-api-plugins/magic-api-plugin-nebula/src/main/java/org/ssssssss/magicapi/nebula/model/Edge.java
@@ -0,0 +1,69 @@
+package org.ssssssss.magicapi.nebula.model;
+
+import java.util.HashMap;
+
+/**
+ * 描述node的方向的边
+ */
+public class Edge {
+
+ /**
+ * 起始节点的id
+ */
+ private String source;
+
+ /**
+ * 终止节点的id
+ */
+ private String target;
+
+ /**
+ * 边描述
+ */
+ private String label;
+
+
+ private String value;
+
+ private HashMap prop = new HashMap<>();
+
+ public String getSource() {
+ return source;
+ }
+
+ public void setSource(String source) {
+ this.source = source;
+ }
+
+ public String getTarget() {
+ return target;
+ }
+
+ public void setTarget(String target) {
+ this.target = target;
+ }
+
+ public String getLabel() {
+ return label;
+ }
+
+ public void setLabel(String label) {
+ this.label = label;
+ }
+
+ public String getValue() {
+ return value;
+ }
+
+ public void setValue(String value) {
+ this.value = value;
+ }
+
+ public HashMap getProp() {
+ return prop;
+ }
+
+ public void setProp(HashMap prop) {
+ this.prop = prop;
+ }
+}
diff --git a/magic-api-plugins/magic-api-plugin-nebula/src/main/java/org/ssssssss/magicapi/nebula/model/NebulaModel.java b/magic-api-plugins/magic-api-plugin-nebula/src/main/java/org/ssssssss/magicapi/nebula/model/NebulaModel.java
new file mode 100644
index 00000000..72d9a38e
--- /dev/null
+++ b/magic-api-plugins/magic-api-plugin-nebula/src/main/java/org/ssssssss/magicapi/nebula/model/NebulaModel.java
@@ -0,0 +1,69 @@
+package org.ssssssss.magicapi.nebula.model;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import org.ssssssss.script.annotation.Comment;
+
+import java.util.*;
+
+/**
+ * 经过加工后的nebula数据结构, 用于前端数据展示
+ * 目前很多前端组件库支持这种数据, 并可视化展示, 如ntV G6等
+ * @see AntV G6
+ */
+public class NebulaModel {
+
+ @JsonIgnore
+ private List nodeIds = new ArrayList<>();
+
+ /**
+ * 包含的节点集合
+ */
+ @Comment("包含的节点集合")
+ private List nodes = new ArrayList<>();
+
+ /**
+ * 包含的边集合
+ */
+
+ @Comment("包含的边集合")
+ private List edges = new ArrayList<>();
+
+ public List getNodeIds() {
+ return nodeIds;
+ }
+
+ public void setNodeIds(List nodeIds) {
+ this.nodeIds = nodeIds;
+ }
+
+ public List getNodes() {
+ return nodes;
+ }
+
+ public void setNodes(List nodes) {
+ this.nodes = nodes;
+ }
+
+ public List getEdges() {
+ return edges;
+ }
+
+ public void setEdges(List edges) {
+ this.edges = edges;
+ }
+
+ /**
+ * 添加节点, 根据id去重
+ * @param node
+ */
+ @Comment("添加节点, 根据id去重")
+ public void addNode(Node node) {
+ String nodeId = Objects.toString(node.getId(), null);
+ if (nodeIds.contains(nodeId)) {
+ return;
+ }
+ nodeIds.add(nodeId);
+ nodes.add(node);
+ }
+
+}
\ No newline at end of file
diff --git a/magic-api-plugins/magic-api-plugin-nebula/src/main/java/org/ssssssss/magicapi/nebula/model/Node.java b/magic-api-plugins/magic-api-plugin-nebula/src/main/java/org/ssssssss/magicapi/nebula/model/Node.java
new file mode 100644
index 00000000..7faf2b54
--- /dev/null
+++ b/magic-api-plugins/magic-api-plugin-nebula/src/main/java/org/ssssssss/magicapi/nebula/model/Node.java
@@ -0,0 +1,36 @@
+package org.ssssssss.magicapi.nebula.model;
+
+import java.util.HashMap;
+
+public class Node {
+
+ private String id;
+
+ private int EdgeSize;
+
+ private HashMap prop = new HashMap<>();
+
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public int getEdgeSize() {
+ return EdgeSize;
+ }
+
+ public void setEdgeSize(int edgeSize) {
+ EdgeSize = edgeSize;
+ }
+
+ public HashMap getProp() {
+ return prop;
+ }
+
+ public void setProp(HashMap prop) {
+ this.prop = prop;
+ }
+}
diff --git a/magic-api-plugins/magic-api-plugin-nebula/src/main/java/org/ssssssss/magicapi/nebula/response/EdgeElement.java b/magic-api-plugins/magic-api-plugin-nebula/src/main/java/org/ssssssss/magicapi/nebula/response/EdgeElement.java
new file mode 100644
index 00000000..864dc6e8
--- /dev/null
+++ b/magic-api-plugins/magic-api-plugin-nebula/src/main/java/org/ssssssss/magicapi/nebula/response/EdgeElement.java
@@ -0,0 +1,14 @@
+package org.ssssssss.magicapi.nebula.response;
+
+public class EdgeElement extends Element {
+
+ private EdgeId id;
+
+ public EdgeId getId() {
+ return id;
+ }
+
+ public void setId(EdgeId id) {
+ this.id = id;
+ }
+}
diff --git a/magic-api-plugins/magic-api-plugin-nebula/src/main/java/org/ssssssss/magicapi/nebula/response/EdgeId.java b/magic-api-plugins/magic-api-plugin-nebula/src/main/java/org/ssssssss/magicapi/nebula/response/EdgeId.java
new file mode 100644
index 00000000..1c706278
--- /dev/null
+++ b/magic-api-plugins/magic-api-plugin-nebula/src/main/java/org/ssssssss/magicapi/nebula/response/EdgeId.java
@@ -0,0 +1,50 @@
+package org.ssssssss.magicapi.nebula.response;
+
+public class EdgeId {
+
+ private String ranking;
+ private String name;
+ private Integer type;
+ private String dst;
+ private String src;
+
+ public String getRanking() {
+ return ranking;
+ }
+
+ public void setRanking(String ranking) {
+ this.ranking = ranking;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public Integer getType() {
+ return type;
+ }
+
+ public void setType(Integer type) {
+ this.type = type;
+ }
+
+ public String getDst() {
+ return dst;
+ }
+
+ public void setDst(String dst) {
+ this.dst = dst;
+ }
+
+ public String getSrc() {
+ return src;
+ }
+
+ public void setSrc(String src) {
+ this.src = src;
+ }
+}
diff --git a/magic-api-plugins/magic-api-plugin-nebula/src/main/java/org/ssssssss/magicapi/nebula/response/Element.java b/magic-api-plugins/magic-api-plugin-nebula/src/main/java/org/ssssssss/magicapi/nebula/response/Element.java
new file mode 100644
index 00000000..69642344
--- /dev/null
+++ b/magic-api-plugins/magic-api-plugin-nebula/src/main/java/org/ssssssss/magicapi/nebula/response/Element.java
@@ -0,0 +1,26 @@
+package org.ssssssss.magicapi.nebula.response;
+
+import com.fasterxml.jackson.annotation.JsonSubTypes;
+import com.fasterxml.jackson.annotation.JsonTypeInfo;
+
+@JsonTypeInfo(
+ use = JsonTypeInfo.Id.NAME,
+ property = "type")
+@JsonSubTypes(value = {
+ @JsonSubTypes.Type(value = EdgeElement.class, name = "edge"),
+ @JsonSubTypes.Type(value = Vertex.class, name = "vertex")
+})
+public abstract class Element {
+
+ protected String type;
+
+
+ public String getType() {
+ return type;
+ }
+
+ public void setType(String type) {
+ this.type = type;
+ }
+
+}
diff --git a/magic-api-plugins/magic-api-plugin-nebula/src/main/java/org/ssssssss/magicapi/nebula/response/NebulaJsonBody.java b/magic-api-plugins/magic-api-plugin-nebula/src/main/java/org/ssssssss/magicapi/nebula/response/NebulaJsonBody.java
new file mode 100644
index 00000000..03652c54
--- /dev/null
+++ b/magic-api-plugins/magic-api-plugin-nebula/src/main/java/org/ssssssss/magicapi/nebula/response/NebulaJsonBody.java
@@ -0,0 +1,132 @@
+package org.ssssssss.magicapi.nebula.response;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+import java.util.HashMap;
+import java.util.List;
+
+public class NebulaJsonBody {
+ private List errors;
+ private List results;
+
+ public List getErrors() {
+ return errors;
+ }
+
+ public void setErrors(List errors) {
+ this.errors = errors;
+ }
+
+
+ public int getErrorCode() {
+ return this.errors.get(0).getCode();
+ }
+
+ public String getErrorMsg() {
+ return this.errors.get(0).getMessage();
+ }
+
+ public List getResults() {
+ return results;
+ }
+
+ public void setResults(List results) {
+ this.results = results;
+ }
+
+
+ public static class NebulaError {
+ private int code;
+ private String message;
+
+ public int getCode() {
+ return code;
+ }
+
+ public void setCode(int code) {
+ this.code = code;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+ }
+
+ public static class Result {
+ @JsonProperty("spaceName")
+ private String spaceName;
+ private List data;
+ private List columns;
+ private NebulaError errors;
+ @JsonProperty("latencyInUs")
+ private long latencyInUs;
+
+ public String getSpaceName() {
+ return spaceName;
+ }
+
+ public void setSpaceName(String spaceName) {
+ this.spaceName = spaceName;
+ }
+
+ public List getData() {
+ return data;
+ }
+
+ public void setData(List data) {
+ this.data = data;
+ }
+
+ public List getColumns() {
+ return columns;
+ }
+
+ public void setColumns(List columns) {
+ this.columns = columns;
+ }
+
+ public NebulaError getErrors() {
+ return errors;
+ }
+
+ public void setErrors(NebulaError errors) {
+ this.errors = errors;
+ }
+
+ public long getLatencyInUs() {
+ return latencyInUs;
+ }
+
+ public void setLatencyInUs(long latencyInUs) {
+ this.latencyInUs = latencyInUs;
+ }
+ }
+
+ public static class Data {
+ private List> meta;
+ private List>> row;
+
+ public List> getMeta() {
+ return meta;
+ }
+
+ public void setMeta(List> meta) {
+ this.meta = meta;
+ }
+
+ public List>> getRow() {
+ return row;
+ }
+
+ public void setRow(List>> row) {
+ this.row = row;
+ }
+ }
+}
+
+
+
diff --git a/magic-api-plugins/magic-api-plugin-nebula/src/main/java/org/ssssssss/magicapi/nebula/response/Vertex.java b/magic-api-plugins/magic-api-plugin-nebula/src/main/java/org/ssssssss/magicapi/nebula/response/Vertex.java
new file mode 100644
index 00000000..43dbded6
--- /dev/null
+++ b/magic-api-plugins/magic-api-plugin-nebula/src/main/java/org/ssssssss/magicapi/nebula/response/Vertex.java
@@ -0,0 +1,14 @@
+package org.ssssssss.magicapi.nebula.response;
+
+public class Vertex extends Element {
+
+ private String id;
+
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+}
diff --git a/magic-api-plugins/magic-api-plugin-nebula/src/main/resources/META-INF/spring.factories b/magic-api-plugins/magic-api-plugin-nebula/src/main/resources/META-INF/spring.factories
new file mode 100644
index 00000000..5c0648a4
--- /dev/null
+++ b/magic-api-plugins/magic-api-plugin-nebula/src/main/resources/META-INF/spring.factories
@@ -0,0 +1 @@
+org.springframework.boot.autoconfigure.EnableAutoConfiguration=org.ssssssss.magicapi.nebula.MagicNebulaConfiguration
\ No newline at end of file
diff --git a/magic-api-plugins/magic-api-plugin-nebula/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/magic-api-plugins/magic-api-plugin-nebula/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
new file mode 100644
index 00000000..e77bfd5f
--- /dev/null
+++ b/magic-api-plugins/magic-api-plugin-nebula/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
@@ -0,0 +1 @@
+org.ssssssss.magicapi.nebula.MagicNebulaConfiguration
\ No newline at end of file
diff --git a/magic-api-plugins/pom.xml b/magic-api-plugins/pom.xml
index f63a46e2..2522a3a6 100644
--- a/magic-api-plugins/pom.xml
+++ b/magic-api-plugins/pom.xml
@@ -23,6 +23,7 @@
magic-api-plugin-elasticsearch
magic-api-plugin-cluster
magic-api-plugin-git
+ magic-api-plugin-nebula
diff --git a/pom.xml b/pom.xml
index f8f65fc2..7b558e24 100644
--- a/pom.xml
+++ b/pom.xml
@@ -33,7 +33,7 @@
1.8.8
1.21
2.7
- 1.6
+ 1.10.0
1.9.4
6.0.0
1.2.83