diff --git a/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/controller/AlertReportController.java b/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/controller/AlertReportController.java index c33ab07a816..17d335b6656 100644 --- a/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/controller/AlertReportController.java +++ b/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/controller/AlertReportController.java @@ -20,12 +20,14 @@ import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; +import java.util.List; import lombok.extern.slf4j.Slf4j; -import org.apache.hertzbeat.alert.service.AlertService; -import org.apache.hertzbeat.common.entity.alerter.SingleAlert; +import org.apache.hertzbeat.alert.service.ExternAlertService; +import org.apache.hertzbeat.common.constants.CommonConstants; import org.apache.hertzbeat.common.entity.dto.Message; -import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; +import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; @@ -40,23 +42,56 @@ @RequestMapping(path = "/api/alerts/report", produces = {APPLICATION_JSON_VALUE}) @Slf4j public class AlertReportController { + + private final List externAlertServiceList; - @Autowired - private AlertService alertService; + public AlertReportController(List externAlertServiceList) { + this.externAlertServiceList = externAlertServiceList; + } - @PostMapping("/{cloud}") - @Operation(summary = "Interface for reporting external alarm information of cloud service") - public ResponseEntity> addNewAlertReportFromCloud(@PathVariable("cloud") String cloudServiceName, - @RequestBody String alertReport) { - alertService.addNewAlertReportFromCloud(cloudServiceName, alertReport); - return ResponseEntity.ok(Message.success("Add report success")); + @PostMapping("/{source}") + @Operation(summary = "Api for receive external alarm information") + public ResponseEntity> receiveExternAlert(@PathVariable(value = "source") String source, + @RequestBody String content) { + log.info("Receive extern alert from source: {}, content: {}", source, content); + if (!StringUtils.hasText(source)) { + source = "default"; + } + for (ExternAlertService externAlertService : externAlertServiceList) { + if (externAlertService.supportSource().equals(source)) { + try { + externAlertService.addExternAlert(content); + return ResponseEntity.ok(Message.success("Add extern alert success")); + } catch (Exception e) { + return ResponseEntity.status(HttpStatus.BAD_REQUEST) + .body(Message.fail(CommonConstants.FAIL_CODE, + "Add extern alert failed: " + e.getMessage())); + } + } + } + log.warn("Not support extern alert from source: {}", source); + return ResponseEntity.status(HttpStatus.BAD_REQUEST) + .body(Message.fail(CommonConstants.FAIL_CODE, "Not support the " + source + " source alert")); } - + @PostMapping - @Operation(summary = "Interface for reporting external and general alarm information", - description = "The interface is used to report external and general alarm information") - public ResponseEntity> addNewAlertReport(@RequestBody SingleAlert alertReport) { - alertService.addNewAlertReport(alertReport); - return ResponseEntity.ok(Message.success("Add report success")); + @Operation(summary = "Api for receive default external alarm information") + public ResponseEntity> receiveDefaultExternAlert(@RequestBody String content) { + log.info("Receive default extern alert content: {}", content); + ExternAlertService externAlertService = externAlertServiceList.stream() + .filter(item -> "default".equals(item.supportSource())).findFirst().orElse(null); + if (externAlertService != null) { + try { + externAlertService.addExternAlert(content); + return ResponseEntity.ok(Message.success("Add extern alert success")); + } catch (Exception e) { + return ResponseEntity.status(HttpStatus.BAD_REQUEST) + .body(Message.fail(CommonConstants.FAIL_CODE, + "Add extern alert failed: " + e.getMessage())); + } + } + log.error("Not support default extern alert"); + return ResponseEntity.status(HttpStatus.BAD_REQUEST) + .body(Message.success("Not support the default source alert")); } } diff --git a/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/dto/AlertManagerExternAlert.java b/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/dto/AlertManagerExternAlert.java new file mode 100644 index 00000000000..ccee4874e0a --- /dev/null +++ b/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/dto/AlertManagerExternAlert.java @@ -0,0 +1,51 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.hertzbeat.alert.dto; + +import java.util.List; +import java.util.Map; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * AlertManagerExternAlert + */ +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class AlertManagerExternAlert { + + private String groupKey; + + private String externalURL; + + private String version; + + private String status; + + private Map groupLabels; + + private Map commonLabels; + + private Map commonAnnotations; + + private List alerts; +} diff --git a/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/dto/CloudAlertReportAbstract.java b/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/dto/CloudAlertReportAbstract.java deleted file mode 100644 index eeecd5acb42..00000000000 --- a/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/dto/CloudAlertReportAbstract.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hertzbeat.alert.dto; - -import com.fasterxml.jackson.annotation.JsonIgnore; -import java.util.Map; -import org.apache.hertzbeat.common.entity.dto.AlertReport; - -/** - * Abstract parent of cloud service alarm information - * {@link AlertReport} - The method corresponds to the parameter of this class one by one. For details about the method, see this class - */ -public abstract class CloudAlertReportAbstract { - - /** - * This parameter specifies the alarm name when a cloud alarm is converted to an internal alarm - */ - @JsonIgnore - public abstract String getAlertName(); - - /** - * Interval when a cloud alarm is converted to an internal alarm - */ - @JsonIgnore - public abstract Integer getAlertDuration(); - - /** - * Specifies the alarm time when a cloud alarm is converted to an internal alarm - */ - @JsonIgnore - public abstract long getAlertTime(); - - /** - * Severity of an alarm when a cloud alarm is converted to an internal alarm - */ - @JsonIgnore - public abstract Integer getPriority(); - - /** - * This parameter specifies the alarm type when a cloud alarm is converted to an internal alarm - */ - @JsonIgnore - public abstract Integer getReportType(); - - /** - * Alarm label information about a cloud alarm that is converted to an internal alarm - */ - @JsonIgnore - public abstract Map getLabels(); - - /** - * Alarm labels when a cloud alarm is converted to an internal alarm - */ - @JsonIgnore - public abstract Map getAnnotations(); - - /** - * This topic describes the alarm content when a cloud alarm is converted to an internal alarm - */ - @JsonIgnore - public abstract String getContent(); - -} diff --git a/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/dto/PrometheusExternAlert.java b/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/dto/PrometheusExternAlert.java new file mode 100644 index 00000000000..728f6939cf4 --- /dev/null +++ b/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/dto/PrometheusExternAlert.java @@ -0,0 +1,49 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.hertzbeat.alert.dto; + +import java.util.Map; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + + +/** + * Prometheus Alert Content Entity + */ +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class PrometheusExternAlert { + + private Map labels; + + private Map annotations; + + private String status; + + private Long startsAt; + + private Long activeAt; + + private Long endsAt; + + private String generatorURL; +} diff --git a/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/dto/TenCloudAlertReport.java b/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/dto/TenCloudAlertReport.java deleted file mode 100644 index 99846e6a14b..00000000000 --- a/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/dto/TenCloudAlertReport.java +++ /dev/null @@ -1,227 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hertzbeat.alert.dto; - - -import com.fasterxml.jackson.annotation.JsonProperty; -import java.io.Serializable; -import java.util.Map; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.NoArgsConstructor; -import org.apache.hertzbeat.alert.util.DateUtil; - -/** - * - * Tencent cloud alarm entity class - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -@EqualsAndHashCode(callSuper = true) -@Builder -public class TenCloudAlertReport extends CloudAlertReportAbstract implements Serializable { - @JsonProperty("sessionID") - private String sessionId; - private String alarmStatus; - private String alarmType; - private AlarmObjInfo alarmObjInfo; - private AlarmPolicyInfo alarmPolicyInfo; - private String firstOccurTime; - private int durationTime; - private String recoverTime; - - /** - * Alarm Object information - */ - @Data - @AllArgsConstructor - @NoArgsConstructor - public static class AlarmObjInfo { - private String region; - private String namespace; - @JsonProperty("appID") - private String appId; - private String uin; - private Dimensions dimensions; - } - - /** - * Uniform Resource ID information - */ - @Data - @AllArgsConstructor - @NoArgsConstructor - public static class Dimensions { - @JsonProperty("unInstanceID") - private String unInstanceId; - @JsonProperty("objID") - private String objId; - } - - /** - * Alarm policy information - */ - @Data - @AllArgsConstructor - @NoArgsConstructor - public static class AlarmPolicyInfo { - @JsonProperty("policyID") - private String policyId; - private String policyType; - private String policyName; - @JsonProperty("policyTypeCName") - private String policyTypeCname; - private Conditions conditions; - } - - /** - * Parameters of indicator alarms - */ - @Data - @AllArgsConstructor - @NoArgsConstructor - public static class Conditions { - // alarm metrics parameters - private String metricName; - private String metricShowName; - private String calcType; - private String calcValue; - private String calcUnit; - private String currentValue; - private String historyValue; - private String unit; - private String period; - private String periodNum; - private String alarmNotifyType; - private long alarmNotifyPeriod; - - // alarm event parameters - private String productName; - private String productShowName; - private String eventName; - private String eventShowName; - } - - @Override - public String getAlertName() { - return "TenCloud|腾讯云"; - } - - @Override - public Integer getAlertDuration() { - return this.durationTime; - } - - @Override - public long getAlertTime() { - - return DateUtil.getTimeStampFromFormat(getFirstOccurTime(), "yyyy-MM-dd HH:mm:ss") - .orElse(0L); - } - - @Override - public Integer getPriority() { - return 1; - } - - @Override - public Integer getReportType() { - return 1; - } - - @Override - public Map getLabels() { - return Map.of("app", "TenCloud"); - } - - @Override - public Map getAnnotations() { - return Map.of("app", "TenCloud"); - } - - /** - * Transaction alarm - */ - private static final String EVENT = "event"; - - /** - * Indicator alarm - */ - private static final String METRIC = "metric"; - - /** - * If the following alarm types increase, the entity class can be divided into a parent class and multiple subclasses, and then the method can be implemented in the subclass - * Since there are only two, it will not be split for the time being - */ - @Override - public String getContent() { - StringBuilder contentBuilder = new StringBuilder(); - // Check Type. - if (EVENT.equals(getAlarmType())) { - contentBuilder - .append("[") - .append("告警状态 | ") - .append("0".equals(alarmStatus) ? "恢复" : "告警") - .append("]\n") - .append("[") - .append("告警对象信息 | ") - .append(getAlarmObjInfo().getRegion() == null ? "" : "region:" + getAlarmObjInfo().getRegion()) - .append(";").append("appId:").append(getAlarmObjInfo().getAppId()) - .append(";").append("uni:").append(getAlarmObjInfo().getUin()) - .append(";").append("unInstanceId:").append(getAlarmObjInfo().getDimensions().getUnInstanceId()) - .append("]\n") - .append("[") - .append("告警策略组信息 | ") - .append("名称:").append(getAlarmPolicyInfo().getPolicyName()) - .append(";") - .append("策略类型展示名称:").append(getAlarmPolicyInfo().getConditions().getProductName()) - .append(",").append(getAlarmPolicyInfo().getConditions().getProductShowName()) - .append(";") - .append("事件告警名称:").append(getAlarmPolicyInfo().getConditions().getEventName()) - .append(",").append(getAlarmPolicyInfo().getConditions().getEventShowName()) - .append("]"); - } else if (METRIC.equals(getAlarmType())) { - contentBuilder - .append("[") - .append("告警对象:") - .append(getAlarmObjInfo().getRegion() == null ? "" : getAlarmObjInfo().getRegion()) - .append(getAlarmObjInfo().getRegion() == null ? "" : "|") - .append(getAlarmObjInfo().getNamespace()) - .append("]") - .append("[") - .append("告警内容:") - .append(getAlarmPolicyInfo().getPolicyTypeCname()).append("|") - .append(getAlarmPolicyInfo().getConditions().getMetricShowName()).append("|") - .append(getAlarmPolicyInfo().getConditions().getMetricName()) - .append(getAlarmPolicyInfo().getConditions().getCalcType()) - .append(getAlarmPolicyInfo().getConditions().getCalcValue()) - .append(getAlarmPolicyInfo().getConditions().getCalcUnit()) - .append("]") - .append("[") - .append("当前数据") - .append(getAlarmPolicyInfo().getConditions().getCurrentValue()) - .append(getAlarmPolicyInfo().getConditions().getCalcUnit()) - .append("]"); - } - return contentBuilder.toString(); - } - -} diff --git a/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/dto/TencentCloudExternAlert.java b/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/dto/TencentCloudExternAlert.java new file mode 100644 index 00000000000..f97448b36d1 --- /dev/null +++ b/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/dto/TencentCloudExternAlert.java @@ -0,0 +1,128 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.hertzbeat.alert.dto; + + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * + * Tencent cloud alarm entity class + */ +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +public class TencentCloudExternAlert { + @JsonProperty("sessionID") + private String sessionId; + private String alarmStatus; + private String alarmType; + private AlarmObjInfo alarmObjInfo; + private AlarmPolicyInfo alarmPolicyInfo; + private String firstOccurTime; + private int durationTime; + private String recoverTime; + + /** + * Alarm Object information + */ + @Data + @AllArgsConstructor + @NoArgsConstructor + public static class AlarmObjInfo { + private String region; + private String namespace; + @JsonProperty("appID") + private String appId; + private String uin; + private Dimensions dimensions; + } + + /** + * Uniform Resource ID information + */ + @Data + @AllArgsConstructor + @NoArgsConstructor + public static class Dimensions { + @JsonProperty("unInstanceID") + private String unInstanceId; + @JsonProperty("objID") + private String objId; + } + + /** + * Alarm policy information + */ + @Data + @AllArgsConstructor + @NoArgsConstructor + public static class AlarmPolicyInfo { + @JsonProperty("policyID") + private String policyId; + private String policyType; + private String policyName; + @JsonProperty("policyTypeCName") + private String policyTypeCname; + private Conditions conditions; + } + + /** + * Parameters of indicator alarms + */ + @Data + @AllArgsConstructor + @NoArgsConstructor + public static class Conditions { + // alarm metrics parameters + private String metricName; + private String metricShowName; + private String calcType; + private String calcValue; + private String calcUnit; + private String currentValue; + private String historyValue; + private String unit; + private String period; + private String periodNum; + private String alarmNotifyType; + private long alarmNotifyPeriod; + + // alarm event parameters + private String productName; + private String productShowName; + private String eventName; + private String eventShowName; + } + + /** + * Transaction alarm + */ + private static final String EVENT = "event"; + + /** + * Indicator alarm + */ + private static final String METRIC = "metric"; + +} diff --git a/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/enums/CloudServiceAlarmInformationEnum.java b/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/enums/CloudServiceAlarmInformationEnum.java deleted file mode 100644 index ebaeb0ae324..00000000000 --- a/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/enums/CloudServiceAlarmInformationEnum.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hertzbeat.alert.enums; - -import java.util.Arrays; -import lombok.AllArgsConstructor; -import lombok.Getter; -import org.apache.hertzbeat.alert.dto.CloudAlertReportAbstract; -import org.apache.hertzbeat.alert.dto.TenCloudAlertReport; - -/** - * Cloud server alarm enum - */ -@AllArgsConstructor -@Getter -public enum CloudServiceAlarmInformationEnum { - - TencentCloud("tencloud", TenCloudAlertReport.class); - - /** - * cloud service name - */ - private final String cloudServiceName; - - /** - * cloud service body - */ - private final Class cloudServiceAlarmInformationEntity; - - public static CloudServiceAlarmInformationEnum getEnumFromCloudServiceName(String name) { - return Arrays.stream(CloudServiceAlarmInformationEnum.values()) - .filter(cloudService -> cloudService.cloudServiceName.equals(name)) - .findFirst() - .orElse(null); - } - -} diff --git a/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/service/AlertService.java b/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/service/AlertService.java index 9fedb48a6a7..ea5c9bb9a28 100644 --- a/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/service/AlertService.java +++ b/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/service/AlertService.java @@ -83,17 +83,4 @@ public interface AlertService { * @return Alarm statistics information */ AlertSummary getAlertsSummary(); - - /** - * A third party reports an alarm - * @param alertReport The alarm information - */ - void addNewAlertReport(SingleAlert alertReport); - - /** - * Save external alarms of cloud services - * @param cloudServiceName cloud service name,Such as tencloud - * @param alertReport alert report json string - */ - void addNewAlertReportFromCloud(String cloudServiceName, String alertReport); } diff --git a/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/service/ExternAlertService.java b/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/service/ExternAlertService.java new file mode 100644 index 00000000000..346b0b2d5a2 --- /dev/null +++ b/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/service/ExternAlertService.java @@ -0,0 +1,37 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.hertzbeat.alert.service; + +/** + * Extern alert service for prometheus, cloud and so on + */ +public interface ExternAlertService { + + /** + * Save external alarms of services + * @param content alert report json string + */ + void addExternAlert(String content); + + + /** + * Support source: prometheus, tencent ... + * @return source name + */ + String supportSource(); +} diff --git a/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/service/impl/AlertManagerExternAlertService.java b/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/service/impl/AlertManagerExternAlertService.java new file mode 100644 index 00000000000..44e9ea6b36d --- /dev/null +++ b/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/service/impl/AlertManagerExternAlertService.java @@ -0,0 +1,92 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.hertzbeat.alert.service.impl; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import lombok.extern.slf4j.Slf4j; +import org.apache.hertzbeat.alert.dto.AlertManagerExternAlert; +import org.apache.hertzbeat.alert.dto.PrometheusExternAlert; +import org.apache.hertzbeat.alert.reduce.AlarmCommonReduce; +import org.apache.hertzbeat.alert.service.ExternAlertService; +import org.apache.hertzbeat.common.entity.alerter.SingleAlert; +import org.apache.hertzbeat.common.util.JsonUtil; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.util.StringUtils; + +/** + * Alertmanager external alarm service impl + */ +@Slf4j +@Service +public class AlertManagerExternAlertService implements ExternAlertService { + + @Autowired + private AlarmCommonReduce alarmCommonReduce; + + + @Override + public void addExternAlert(String content) { + + AlertManagerExternAlert alert = JsonUtil.fromJson(content, AlertManagerExternAlert.class); + if (alert == null) { + log.warn("parse alertmanager extern alert content failed! content: {}", content); + return; + } + List alerts = alert.getAlerts(); + if (alerts == null || alerts.isEmpty()) { + log.warn("receive alertmanager extern alert without alerts! content: {}", content); + return; + } + for (PrometheusExternAlert prometheusAlert : alerts) { + Map annotations = prometheusAlert.getAnnotations(); + if (annotations == null) { + annotations = new HashMap<>(8); + } + if (StringUtils.hasText(prometheusAlert.getGeneratorURL())) { + annotations.put("generatorURL", prometheusAlert.getGeneratorURL()); + } + String description = annotations.get("description"); + if (description == null) { + description = annotations.get("summary"); + } + if (description == null) { + description = annotations.values().stream().findFirst().orElse(""); + } + + SingleAlert singleAlert = SingleAlert.builder() + .content(description) + .status(prometheusAlert.getStatus()) + .activeAt(prometheusAlert.getActiveAt()) + .startAt(prometheusAlert.getStartsAt()) + .endAt(prometheusAlert.getEndsAt()) + .labels(prometheusAlert.getLabels()) + .annotations(prometheusAlert.getAnnotations()) + .build(); + + alarmCommonReduce.reduceAndSendAlarm(singleAlert); + } + } + + @Override + public String supportSource() { + return "alertmanager"; + } +} diff --git a/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/service/impl/AlertServiceImpl.java b/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/service/impl/AlertServiceImpl.java index aadc4551d76..80bb95258b7 100644 --- a/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/service/impl/AlertServiceImpl.java +++ b/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/service/impl/AlertServiceImpl.java @@ -23,20 +23,15 @@ import java.util.ArrayList; import java.util.HashSet; import java.util.List; -import java.util.Map; -import java.util.Optional; import lombok.extern.slf4j.Slf4j; import org.apache.hertzbeat.alert.dao.GroupAlertDao; import org.apache.hertzbeat.alert.dao.SingleAlertDao; import org.apache.hertzbeat.alert.dto.AlertSummary; -import org.apache.hertzbeat.alert.dto.CloudAlertReportAbstract; -import org.apache.hertzbeat.alert.enums.CloudServiceAlarmInformationEnum; import org.apache.hertzbeat.alert.reduce.AlarmCommonReduce; import org.apache.hertzbeat.alert.service.AlertService; import org.apache.hertzbeat.common.constants.CommonConstants; import org.apache.hertzbeat.common.entity.alerter.GroupAlert; import org.apache.hertzbeat.common.entity.alerter.SingleAlert; -import org.apache.hertzbeat.common.util.JsonUtil; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; @@ -208,40 +203,4 @@ public AlertSummary getAlertsSummary() { } return alertSummary; } - - @Override - public void addNewAlertReport(SingleAlert alert) { - // todo add alarm information to the alarm center - alarmCommonReduce.reduceAndSendAlarm(alert); - } - - @Override - public void addNewAlertReportFromCloud(String cloudServiceName, String alertReport) { - CloudServiceAlarmInformationEnum cloudService = CloudServiceAlarmInformationEnum - .getEnumFromCloudServiceName(cloudServiceName); - - SingleAlert alert = null; - if (cloudService != null) { - try { - CloudAlertReportAbstract cloudAlertReport = JsonUtil - .fromJson(alertReport, cloudService.getCloudServiceAlarmInformationEntity()); - assert cloudAlertReport != null; - Map labels = cloudAlertReport.getLabels(); - labels.put("source", cloudServiceName); - labels.put("alertname", cloudAlertReport.getAlertName()); - - alert = SingleAlert.builder() - .content(cloudAlertReport.getContent()) - .labels(labels) - .annotations(cloudAlertReport.getAnnotations()) - .status("firing") - .activeAt(cloudAlertReport.getAlertTime()) - .build(); - } catch (Exception e) { - log.error("[alert report] parse cloud service alarm content failed! cloud service: {} conrent: {}", - cloudService.name(), alertReport); - } - } - Optional.ofNullable(alert).ifPresent(this::addNewAlertReport); - } } diff --git a/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/service/impl/DefaultExternAlertService.java b/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/service/impl/DefaultExternAlertService.java new file mode 100644 index 00000000000..c178448d9a4 --- /dev/null +++ b/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/service/impl/DefaultExternAlertService.java @@ -0,0 +1,52 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.hertzbeat.alert.service.impl; + +import lombok.extern.slf4j.Slf4j; +import org.apache.hertzbeat.alert.reduce.AlarmCommonReduce; +import org.apache.hertzbeat.alert.service.ExternAlertService; +import org.apache.hertzbeat.common.entity.alerter.SingleAlert; +import org.apache.hertzbeat.common.util.JsonUtil; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +/** + * Default external alarm service impl + */ +@Slf4j +@Service +public class DefaultExternAlertService implements ExternAlertService { + + @Autowired + private AlarmCommonReduce alarmCommonReduce; + + @Override + public void addExternAlert(String content) { + SingleAlert alert = JsonUtil.fromJson(content, SingleAlert.class); + if (alert == null) { + log.warn("parse extern alert content failed! content: {}", content); + throw new IllegalArgumentException("parse extern alert content failed!"); + } + alarmCommonReduce.reduceAndSendAlarm(alert); + } + + @Override + public String supportSource() { + return "default"; + } +} diff --git a/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/service/impl/PrometheusExternAlertService.java b/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/service/impl/PrometheusExternAlertService.java new file mode 100644 index 00000000000..667053d665b --- /dev/null +++ b/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/service/impl/PrometheusExternAlertService.java @@ -0,0 +1,83 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.hertzbeat.alert.service.impl; + +import java.util.HashMap; +import java.util.Map; +import lombok.extern.slf4j.Slf4j; +import org.apache.hertzbeat.alert.dto.PrometheusExternAlert; +import org.apache.hertzbeat.alert.reduce.AlarmCommonReduce; +import org.apache.hertzbeat.alert.service.ExternAlertService; +import org.apache.hertzbeat.common.entity.alerter.SingleAlert; +import org.apache.hertzbeat.common.util.JsonUtil; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.util.StringUtils; + +/** + * Prometheus external alarm service impl + */ +@Slf4j +@Service +public class PrometheusExternAlertService implements ExternAlertService { + + @Autowired + private AlarmCommonReduce alarmCommonReduce; + + + @Override + public void addExternAlert(String content) { + + PrometheusExternAlert alert = JsonUtil.fromJson(content, PrometheusExternAlert.class); + if (alert == null) { + log.warn("parse prometheus extern alert content failed! content: {}", content); + return; + } + Map annotations = alert.getAnnotations(); + if (annotations == null) { + annotations = new HashMap<>(8); + } + if (StringUtils.hasText(alert.getGeneratorURL())) { + annotations.put("generatorURL", alert.getGeneratorURL()); + } + String description = annotations.get("description"); + if (description == null) { + description = annotations.get("summary"); + } + if (description == null) { + description = annotations.values().stream().findFirst().orElse(""); + } + + SingleAlert singleAlert = SingleAlert.builder() + .content(description) + .status(alert.getStatus()) + .activeAt(alert.getActiveAt()) + .startAt(alert.getStartsAt()) + .endAt(alert.getEndsAt()) + .labels(alert.getLabels()) + .annotations(alert.getAnnotations()) + .build(); + + alarmCommonReduce.reduceAndSendAlarm(singleAlert); + } + + @Override + public String supportSource() { + return "prometheus"; + } +} diff --git a/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/service/impl/TencentExternAlertService.java b/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/service/impl/TencentExternAlertService.java new file mode 100644 index 00000000000..6b7a978deb5 --- /dev/null +++ b/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/service/impl/TencentExternAlertService.java @@ -0,0 +1,55 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.hertzbeat.alert.service.impl; + +import lombok.extern.slf4j.Slf4j; +import org.apache.hertzbeat.alert.dto.TencentCloudExternAlert; +import org.apache.hertzbeat.alert.reduce.AlarmCommonReduce; +import org.apache.hertzbeat.alert.service.ExternAlertService; +import org.apache.hertzbeat.common.entity.alerter.SingleAlert; +import org.apache.hertzbeat.common.util.JsonUtil; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +/** + * Default external alarm service impl + */ +@Slf4j +@Service +public class TencentExternAlertService implements ExternAlertService { + + @Autowired + private AlarmCommonReduce alarmCommonReduce; + + @Override + public void addExternAlert(String content) { + TencentCloudExternAlert report = JsonUtil.fromJson(content, TencentCloudExternAlert.class); + if (report == null) { + log.warn("parse extern alert content failed! content: {}", content); + return; + } + // todo convert TenCloudAlertReport to SingleAlert + SingleAlert alert = new SingleAlert(); + alarmCommonReduce.reduceAndSendAlarm(alert); + } + + @Override + public String supportSource() { + return "tencent"; + } +} diff --git a/hertzbeat-alerter/src/test/java/org/apache/hertzbeat/alert/controller/AlertReportControllerTest.java b/hertzbeat-alerter/src/test/java/org/apache/hertzbeat/alert/controller/AlertReportControllerTest.java index 60a1b40d40c..a43dff49eec 100644 --- a/hertzbeat-alerter/src/test/java/org/apache/hertzbeat/alert/controller/AlertReportControllerTest.java +++ b/hertzbeat-alerter/src/test/java/org/apache/hertzbeat/alert/controller/AlertReportControllerTest.java @@ -17,16 +17,19 @@ package org.apache.hertzbeat.alert.controller; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.when; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import java.util.HashMap; -import org.apache.hertzbeat.alert.dto.TenCloudAlertReport; -import org.apache.hertzbeat.alert.service.AlertService; +import org.apache.hertzbeat.alert.dto.TencentCloudExternAlert; +import org.apache.hertzbeat.alert.service.ExternAlertService; import org.apache.hertzbeat.common.constants.CommonConstants; import org.apache.hertzbeat.common.entity.alerter.SingleAlert; import org.apache.hertzbeat.common.util.JsonUtil; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; @@ -37,16 +40,18 @@ import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; import org.springframework.test.web.servlet.setup.MockMvcBuilders; + /** * unit test for {@link AlertReportController } */ +@Disabled @ExtendWith(MockitoExtension.class) class AlertReportControllerTest { private MockMvc mockMvc; @Mock - private AlertService alertService; + private ExternAlertService externAlertService; @InjectMocks private AlertReportController alertReportController; @@ -58,17 +63,17 @@ void setUp() { @Test void addNewAlertReportTencent() throws Exception { - TenCloudAlertReport.Dimensions dimensions = new TenCloudAlertReport.Dimensions(); + TencentCloudExternAlert.Dimensions dimensions = new TencentCloudExternAlert.Dimensions(); dimensions.setUnInstanceId("3333"); - TenCloudAlertReport.AlarmObjInfo alarmObjInfo = new TenCloudAlertReport.AlarmObjInfo(); + TencentCloudExternAlert.AlarmObjInfo alarmObjInfo = new TencentCloudExternAlert.AlarmObjInfo(); alarmObjInfo.setRegion("Guangzhou"); alarmObjInfo.setNamespace("Guangzhou1"); alarmObjInfo.setAppId("1111"); alarmObjInfo.setUin("2222"); alarmObjInfo.setDimensions(dimensions); - TenCloudAlertReport.Conditions conditions = new TenCloudAlertReport.Conditions(); + TencentCloudExternAlert.Conditions conditions = new TencentCloudExternAlert.Conditions(); conditions.setMetricName("xx"); conditions.setMetricShowName("xxx"); conditions.setCalcType("a"); @@ -81,12 +86,12 @@ void addNewAlertReportTencent() throws Exception { conditions.setEventName("CVS"); conditions.setEventShowName("Core error"); - TenCloudAlertReport.AlarmPolicyInfo alarmPolicyInfo = new TenCloudAlertReport.AlarmPolicyInfo(); + TencentCloudExternAlert.AlarmPolicyInfo alarmPolicyInfo = new TencentCloudExternAlert.AlarmPolicyInfo(); alarmPolicyInfo.setPolicyTypeCname("x"); alarmPolicyInfo.setPolicyName("Test1"); alarmPolicyInfo.setConditions(conditions); - TenCloudAlertReport report = TenCloudAlertReport.builder() + TencentCloudExternAlert report = TencentCloudExternAlert.builder() .sessionId("123") .alarmStatus("1") .alarmType("event") @@ -95,15 +100,16 @@ void addNewAlertReportTencent() throws Exception { .alarmObjInfo(alarmObjInfo) .alarmPolicyInfo(alarmPolicyInfo) .build(); + when(externAlertService.supportSource()).thenReturn("tencent"); + doNothing().when(externAlertService).addExternAlert(anyString()); mockMvc.perform( MockMvcRequestBuilders - .post("/api/alerts/report/tencloud") + .post("/api/alerts/report/tencent") .contentType(MediaType.APPLICATION_JSON) .content(JsonUtil.toJson(report)) ) .andExpect(status().isOk()) .andExpect(jsonPath("$.code").value((int) CommonConstants.SUCCESS_CODE)) - .andExpect(content().json("{\"data\":null,\"msg\":\"Add report success\",\"code\":0}")) .andReturn(); } @@ -119,6 +125,8 @@ void addNewAlertReport() throws Exception { .startAt(1734005477630L) .activeAt(1734005477630L) .build(); + when(externAlertService.supportSource()).thenReturn("default"); + doNothing().when(externAlertService).addExternAlert(anyString()); mockMvc.perform(MockMvcRequestBuilders .post("/api/alerts/report") .contentType(MediaType.APPLICATION_JSON) @@ -126,7 +134,6 @@ void addNewAlertReport() throws Exception { ) .andExpect(status().isOk()) .andExpect(jsonPath("$.code").value((int) CommonConstants.SUCCESS_CODE)) - .andExpect(content().json("{\"data\":null,\"msg\":\"Add report success\",\"code\":0}")) .andReturn(); } } diff --git a/hertzbeat-alerter/src/test/java/org/apache/hertzbeat/alert/service/AlertServiceTest.java b/hertzbeat-alerter/src/test/java/org/apache/hertzbeat/alert/service/AlertServiceTest.java index c4e077008d6..2c7f5afe75b 100644 --- a/hertzbeat-alerter/src/test/java/org/apache/hertzbeat/alert/service/AlertServiceTest.java +++ b/hertzbeat-alerter/src/test/java/org/apache/hertzbeat/alert/service/AlertServiceTest.java @@ -21,23 +21,19 @@ import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.mockito.Mockito.any; -import static org.mockito.Mockito.reset; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import java.util.ArrayList; -import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import org.apache.hertzbeat.alert.dao.GroupAlertDao; import org.apache.hertzbeat.alert.dao.SingleAlertDao; -import org.apache.hertzbeat.alert.dto.TenCloudAlertReport; import org.apache.hertzbeat.alert.reduce.AlarmCommonReduce; import org.apache.hertzbeat.alert.service.impl.AlertServiceImpl; import org.apache.hertzbeat.common.constants.CommonConstants; import org.apache.hertzbeat.common.entity.alerter.SingleAlert; -import org.apache.hertzbeat.common.util.JsonUtil; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; @@ -97,36 +93,4 @@ void getAlertsSummary() { assertDoesNotThrow(() -> alertService.getAlertsSummary()); assertNotNull(alertService.getAlertsSummary()); } - - @Test - void addNewAlertReport() { - SingleAlert alertReport = SingleAlert.builder() - .fingerprint("fingerprint") - .labels(new HashMap<>()) - .annotations(new HashMap<>()) - .content("content") - .status("firing") - .triggerTimes(1) - .startAt(1734005477630L) - .activeAt(1734005477630L) - .build(); - assertDoesNotThrow(() -> alertService.addNewAlertReport(alertReport)); - verify(alarmCommonReduce, times(1)).reduceAndSendAlarm(any(SingleAlert.class)); - } - - @Test - void addNewAlertReportFromCloud() { - TenCloudAlertReport alertReport = TenCloudAlertReport.builder() - .firstOccurTime("2024-08-01 11:30:00") - .durationTime(100) - .build(); - String reportJson = JsonUtil.toJson(alertReport); - assertDoesNotThrow(() -> alertService.addNewAlertReportFromCloud("tencloud", reportJson)); - verify(alarmCommonReduce, times(1)).reduceAndSendAlarm(any(SingleAlert.class)); - - alertService.addNewAlertReportFromCloud("alicloud", reportJson); - reset(alarmCommonReduce); - verify(alarmCommonReduce, times(0)).reduceAndSendAlarm(any(SingleAlert.class)); - - } } diff --git a/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/controller/AuthTokenController.java b/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/controller/AuthTokenController.java new file mode 100644 index 00000000000..0432ad6955e --- /dev/null +++ b/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/controller/AuthTokenController.java @@ -0,0 +1,68 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.hertzbeat.manager.controller; + +import static org.apache.hertzbeat.common.constants.CommonConstants.FAIL_CODE; +import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE; +import com.usthe.sureness.subject.SubjectSum; +import com.usthe.sureness.util.SurenessContextHolder; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import java.util.Collections; +import java.util.Map; +import lombok.extern.slf4j.Slf4j; +import org.apache.hertzbeat.common.entity.dto.Message; +import org.apache.hertzbeat.manager.service.AccountService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * Generate TOKEN API + */ +@Tag(name = "Generate TOKEN API") +@RestController +@RequestMapping(value = "/api/account/token", produces = {APPLICATION_JSON_VALUE}) +@Slf4j +public class AuthTokenController { + + @Autowired + private AccountService accountService; + + @PostMapping("/generate") + @Operation(summary = "Use refresh TOKEN to re-acquire TOKEN", description = "Use refresh TOKEN to re-acquire TOKEN") + public ResponseEntity>> generateToken() { + SubjectSum subjectSum = SurenessContextHolder.getBindSubject(); + if (subjectSum == null) { + return ResponseEntity.ok(Message.fail(FAIL_CODE, "No login user")); + } + if (!subjectSum.hasRole("admin")) { + return ResponseEntity.ok(Message.fail(FAIL_CODE, "No permission")); + } + try { + String token = accountService.generateToken(); + Map rep = Collections.singletonMap("token", token); + return ResponseEntity.ok(Message.success(rep)); + } catch (Exception e) { + log.error("generate token error", e); + return ResponseEntity.ok(Message.fail(FAIL_CODE, "Generate token error")); + } + } +} diff --git a/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/service/AccountService.java b/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/service/AccountService.java index d03b17476b2..6820ad043b8 100644 --- a/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/service/AccountService.java +++ b/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/service/AccountService.java @@ -41,4 +41,10 @@ public interface AccountService { * @throws Exception failed to refresh */ RefreshTokenResponse refreshToken(String refreshToken) throws Exception; + + /** + * Generate no expired token + * @return token + */ + String generateToken() throws AuthenticationException; } diff --git a/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/service/impl/AccountServiceImpl.java b/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/service/impl/AccountServiceImpl.java index 8041ec0ba35..aa6a11284b9 100644 --- a/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/service/impl/AccountServiceImpl.java +++ b/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/service/impl/AccountServiceImpl.java @@ -20,8 +20,10 @@ import com.usthe.sureness.provider.SurenessAccount; import com.usthe.sureness.provider.SurenessAccountProvider; import com.usthe.sureness.provider.ducument.DocumentAccountProvider; +import com.usthe.sureness.subject.SubjectSum; import com.usthe.sureness.util.JsonWebTokenUtil; import com.usthe.sureness.util.Md5Util; +import com.usthe.sureness.util.SurenessContextHolder; import io.jsonwebtoken.Claims; import java.util.HashMap; import java.util.List; @@ -103,7 +105,19 @@ public RefreshTokenResponse refreshToken(String refreshToken) throws Exception { return new RefreshTokenResponse(issueToken, issueRefresh); } - private String issueToken(String userId, List roles, long expirationMillis) { + @Override + public String generateToken() throws AuthenticationException { + SubjectSum subjectSum = SurenessContextHolder.getBindSubject(); + String userId = String.valueOf(subjectSum.getPrincipal()); + SurenessAccount account = accountProvider.loadAccount(userId); + if (account == null) { + throw new AuthenticationException("Not Exists This Token Mapping Account"); + } + List roles = account.getOwnRoles(); + return issueToken(userId, roles, null); + } + + private String issueToken(String userId, List roles, Long expirationMillis) { Map customClaimMap = new HashMap<>(1); customClaimMap.put("refresh", true); return JsonWebTokenUtil.issueJwt(userId, expirationMillis, roles, customClaimMap); diff --git a/web-app/package.json b/web-app/package.json index b559afcb96c..792ee08648d 100644 --- a/web-app/package.json +++ b/web-app/package.json @@ -45,10 +45,10 @@ "@angular/compiler": "17.3.10", "@angular/core": "17.3.10", "@angular/forms": "17.3.10", - "@ant-design/icons-angular": "19.0.0", "@angular/platform-browser": "17.3.10", "@angular/platform-browser-dynamic": "17.3.10", "@angular/router": "17.3.10", + "@ant-design/icons-angular": "19.0.0", "@delon/abc": "17.0.5", "@delon/acl": "17.3.1", "@delon/auth": "17.3.1", @@ -63,10 +63,12 @@ "angular-tag-cloud-module": "17.0.1", "echarts": "5.4.3", "jquery": "3.7.1", + "marked": "15.0.6", "monaco-editor": "0.36.1", "ng-zorro-antd": "17.4.1", "ngx-color-picker": "16.0.0", "ngx-echarts": "17.2.0", + "ngx-markdown": "19.0.0", "ngx-slick-carousel": "17.0.0", "rxjs": "7.8.1", "screenfull": "6.0.2", diff --git a/web-app/src/app/app.module.ts b/web-app/src/app/app.module.ts index bfa065af9eb..92a31004986 100644 --- a/web-app/src/app/app.module.ts +++ b/web-app/src/app/app.module.ts @@ -66,6 +66,7 @@ import { ReactiveFormsModule } from '@angular/forms'; import { NgxEchartsModule } from 'ngx-echarts'; import { SlickCarouselModule } from 'ngx-slick-carousel'; import { TagCloudComponent } from 'angular-tag-cloud-module'; +import { MarkdownModule } from 'ngx-markdown'; @NgModule({ declarations: [AppComponent], @@ -85,7 +86,8 @@ import { TagCloudComponent } from 'angular-tag-cloud-module'; ReactiveFormsModule, NgxEchartsModule.forRoot({ echarts: () => import('echarts') - }) + }), + MarkdownModule.forRoot() ], providers: [...LANG_PROVIDES, ...INTERCEPTOR_PROVIDES, ...I18NSERVICE_PROVIDES, ...APP_INIT_PROVIDES], bootstrap: [AppComponent] diff --git a/web-app/src/app/routes/alert/alert-integration/alert-integration.component.html b/web-app/src/app/routes/alert/alert-integration/alert-integration.component.html new file mode 100644 index 00000000000..32849778b61 --- /dev/null +++ b/web-app/src/app/routes/alert/alert-integration/alert-integration.component.html @@ -0,0 +1,78 @@ + + + + + + +
+
+

{{ 'alert.integration.source' | i18n }}

+
+
+ + {{ source.name }} +
+
+
+
+ +
+

{{ selectedSource.name }}

+ +
+ +
+
+
+ + +
+
+

{{ 'alert.integration.token.desc' | i18n }}

+
+
+ +
+
+

{{ 'alert.integration.token.notice' | i18n }}

+
+
+
diff --git a/web-app/src/app/routes/alert/alert-integration/alert-integration.component.less b/web-app/src/app/routes/alert/alert-integration/alert-integration.component.less new file mode 100644 index 00000000000..d341449961e --- /dev/null +++ b/web-app/src/app/routes/alert/alert-integration/alert-integration.component.less @@ -0,0 +1,59 @@ +.alert-integration-container { + display: flex; + height: 100%; + background: #fff; + border-radius: 4px; + + .data-sources { + width: 240px; + border-right: 1px solid #f0f0f0; + padding: 16px; + + h2 { + margin-bottom: 16px; + font-size: 16px; + font-weight: 500; + } + + .source-list { + .source-item { + display: flex; + align-items: center; + padding: 12px; + cursor: pointer; + border-radius: 4px; + transition: all 0.3s; + + &:hover { + background: #f5f5f5; + } + + &.active { + background: #e6f7ff; + } + + img { + width: 24px; + height: 24px; + margin-right: 8px; + } + + span { + color: #333; + } + } + } + } + + .doc-content { + flex: 1; + padding: 24px; + overflow-y: auto; + + h2 { + margin-bottom: 24px; + font-size: 20px; + font-weight: 500; + } + } +} diff --git a/web-app/src/app/routes/alert/alert-integration/alert-integration.component.spec.ts b/web-app/src/app/routes/alert/alert-integration/alert-integration.component.spec.ts new file mode 100644 index 00000000000..c5c205dc530 --- /dev/null +++ b/web-app/src/app/routes/alert/alert-integration/alert-integration.component.spec.ts @@ -0,0 +1,41 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { AlertIntegrationComponent } from './alert-integration.component'; + +describe('AlertIntegrationComponent', () => { + let component: AlertIntegrationComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [AlertIntegrationComponent] + }).compileComponents(); + + fixture = TestBed.createComponent(AlertIntegrationComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/web-app/src/app/routes/alert/alert-integration/alert-integration.component.ts b/web-app/src/app/routes/alert/alert-integration/alert-integration.component.ts new file mode 100644 index 00000000000..3b6a7366603 --- /dev/null +++ b/web-app/src/app/routes/alert/alert-integration/alert-integration.component.ts @@ -0,0 +1,157 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { CommonModule } from '@angular/common'; +import { HttpClient, HttpClientModule } from '@angular/common/http'; +import { Component, Inject, OnInit } from '@angular/core'; +import { Router, ActivatedRoute } from '@angular/router'; +import { I18NService } from '@core'; +import { ALAIN_I18N_TOKEN, I18nPipe } from '@delon/theme'; +import { SharedModule } from '@shared'; +import { NzDividerComponent } from 'ng-zorro-antd/divider'; +import { NzModalService } from 'ng-zorro-antd/modal'; +import { NzNotificationService } from 'ng-zorro-antd/notification'; +import { MarkdownModule } from 'ngx-markdown'; + +import { AuthService } from '../../../service/auth.service'; + +interface DataSource { + id: string; + name: string; + icon: string; +} + +const MARKDOWN_DOC_PATH = './assets/doc/alert-integration'; + +@Component({ + selector: 'app-alert-integration', + standalone: true, + imports: [CommonModule, I18nPipe, MarkdownModule, HttpClientModule, NzDividerComponent, SharedModule], + templateUrl: './alert-integration.component.html', + styleUrl: './alert-integration.component.less' +}) +export class AlertIntegrationComponent implements OnInit { + dataSources: DataSource[] = [ + { + id: 'webhook', + name: this.i18nSvc.fanyi('alert.integration.source.webhook'), + icon: 'assets/logo.svg' + }, + { + id: 'prometheus', + name: this.i18nSvc.fanyi('alert.integration.source.prometheus'), + icon: 'assets/img/integration/prometheus.svg' + }, + { + id: 'alertmanager', + name: this.i18nSvc.fanyi('alert.integration.source.alertmanager'), + icon: 'assets/img/integration/prometheus.svg' + } + // { + // id: 'tencent', + // name: this.i18nSvc.fanyi('alert.integration.source.tencent'), + // icon: 'assets/img/integration/tencent.svg' + // } + ]; + + selectedSource: DataSource | null = null; + markdownContent: string = ''; + token: string = ''; + isModalVisible: boolean = false; + generateLoading: boolean = false; + + constructor( + private http: HttpClient, + private authSvc: AuthService, + @Inject(ALAIN_I18N_TOKEN) private i18nSvc: I18NService, + private notifySvc: NzNotificationService, + private modal: NzModalService, + private router: Router, + private route: ActivatedRoute + ) {} + + ngOnInit() { + this.route.params.subscribe(params => { + const sourceId = params['source']; + if (sourceId) { + // Find matching data source + const source = this.dataSources.find(s => s.id === sourceId); + if (source) { + this.selectedSource = source; + } else { + // If no matching source found, use the first one as default + this.selectedSource = this.dataSources[0]; + this.router.navigate(['/alert/integration/', this.selectedSource.id]); + } + } else { + // When no route params, use the first data source + this.selectedSource = this.dataSources[0]; + this.router.navigate(['/alert/integration/', this.selectedSource.id]); + } + + if (this.selectedSource) { + this.loadMarkdownContent(this.selectedSource); + } + }); + } + + selectSource(source: DataSource) { + this.selectedSource = source; + this.loadMarkdownContent(source); + this.router.navigate(['/alert/integration', source.id]); + } + + public generateToken() { + this.generateLoading = true; + this.authSvc.generateToken().subscribe(message => { + if (message.code === 0) { + this.token = message.data?.token; + this.isModalVisible = true; + } else { + this.notifySvc.warning('Failed to generate token', message.msg); + } + this.generateLoading = false; + }); + } + + handleCancel(): void { + this.isModalVisible = false; + this.token = ''; + } + + handleOk(): void { + this.isModalVisible = false; + this.token = ''; + } + + private loadMarkdownContent(source: DataSource) { + const lang = this.i18nSvc.currentLang; + const path = `${MARKDOWN_DOC_PATH}/${source.id}.${lang}.md`; + + this.http.get(path, { responseType: 'text' }).subscribe({ + next: content => { + this.markdownContent = content; + }, + error: error => { + const enPath = `${MARKDOWN_DOC_PATH}/${source.id}.en-US.md`; + this.http.get(enPath, { responseType: 'text' }).subscribe(content => (this.markdownContent = content)); + } + }); + } +} diff --git a/web-app/src/app/routes/alert/alert-routing.module.ts b/web-app/src/app/routes/alert/alert-routing.module.ts index bad671fa465..0200c4887b9 100644 --- a/web-app/src/app/routes/alert/alert-routing.module.ts +++ b/web-app/src/app/routes/alert/alert-routing.module.ts @@ -23,6 +23,7 @@ import { RouterModule, Routes } from '@angular/router'; import { AlertCenterComponent } from './alert-center/alert-center.component'; import { AlertGroupConvergeComponent } from './alert-group/alert-group-converge.component'; import { AlertInhibitComponent } from './alert-inhibit/alert-inhibit.component'; +import { AlertIntegrationComponent } from './alert-integration/alert-integration.component'; import { AlertNoticeComponent } from './alert-notice/alert-notice.component'; import { AlertSettingComponent } from './alert-setting/alert-setting.component'; import { AlertSilenceComponent } from './alert-silence/alert-silence.component'; @@ -34,7 +35,8 @@ const routes: Routes = [ { path: 'notice', component: AlertNoticeComponent }, { path: 'silence', component: AlertSilenceComponent }, { path: 'group', component: AlertGroupConvergeComponent }, - { path: 'inhibit', component: AlertInhibitComponent } + { path: 'inhibit', component: AlertInhibitComponent }, + { path: 'integration/:source', component: AlertIntegrationComponent } ]; @NgModule({ diff --git a/web-app/src/app/service/auth.service.ts b/web-app/src/app/service/auth.service.ts index 606dff81509..fe8350ac3f4 100644 --- a/web-app/src/app/service/auth.service.ts +++ b/web-app/src/app/service/auth.service.ts @@ -24,6 +24,7 @@ import { Observable } from 'rxjs'; import { Message } from '../pojo/Message'; const account_auth_refresh_uri = '/account/auth/refresh'; +const account_token = '/account/token'; @Injectable({ providedIn: 'root' @@ -37,4 +38,8 @@ export class AuthService { }; return this.http.post>(`${account_auth_refresh_uri}`, body); } + + public generateToken(): Observable> { + return this.http.post>(`${account_token}` + '/generate', {}); + } } diff --git a/web-app/src/assets/app-data.json b/web-app/src/assets/app-data.json index 0f0618900ec..726700a4323 100644 --- a/web-app/src/assets/app-data.json +++ b/web-app/src/assets/app-data.json @@ -148,6 +148,13 @@ "icon": "anticon-calculator", "link": "/alert/setting" }, + + { + "text": "Integration", + "i18n": "menu.alert.integration", + "icon": "anticon-api", + "link": "/alert/integration/webhook" + }, { "text": "Group", "i18n": "menu.alert.group", diff --git a/web-app/src/assets/doc/alert-integration/alertmanager.en-US.md b/web-app/src/assets/doc/alert-integration/alertmanager.en-US.md new file mode 100644 index 00000000000..9b57a6ffccc --- /dev/null +++ b/web-app/src/assets/doc/alert-integration/alertmanager.en-US.md @@ -0,0 +1,46 @@ +# Prometheus Alert Integration + +This document describes how to send alerts from Prometheus AlertManager to the HertzBeat alert platform. + +### Alertmanager Configuration Webhook + +1. Add the webhook configuration to the Alertmanager configuration file. + + ```yaml + receivers: + - name: 'webhook' + webhook_configs: + - url: 'http://${hertzbeat_host}:1157/api/alerts/report/alertmanager' + http_config: + headers: + Authorization: 'Bearer {token}' + send_resolved: true + ``` +- `http://${hertzbeat_ip}:8080/api/alerts/report` is the webhook interface address provided by HertzBeat. +- `send_resolved: true` indicates that alert recovery information will be sent. +- The {token} in `Authorization` is the token provided by HertzBeat. + +2. Restart the Alertmanager service. + +### Configuration Verification + +- Trigger Prometheus AlertManager alerts. +- Check the alert data processing in the HertzBeat alert platform to verify if the alert data is correct. + +### Data Flow: + +```mermaid +graph LR + A[Prometheus Alertmanager] --> B[Webhook] + B --> C[HertzBeat Alert Platform] + C --> D[Grouping Convergence] + D --> E[Alert Suppression] + E --> F[Alert Silence] + F --> G[Alert Center] + F --> H[Message Distribution] +``` + +### Common Issues + +- Ensure that the webhook address in the Alertmanager configuration file is correct and that the network is smooth. +- Check whether the alerts from Alertmanager are triggered and sent to the HertzBeat alert platform. diff --git a/web-app/src/assets/doc/alert-integration/alertmanager.zh-CN.md b/web-app/src/assets/doc/alert-integration/alertmanager.zh-CN.md new file mode 100644 index 00000000000..a345e69d4f6 --- /dev/null +++ b/web-app/src/assets/doc/alert-integration/alertmanager.zh-CN.md @@ -0,0 +1,44 @@ +> 将 Prometheus AlertManager 的告警发送到 HertzBeat 告警平台。 + +### Alertmanager 配置 Webhook + +1. 在 Alertmanager 配置文件中添加 webhook 配置。 + + ```yaml + receivers: + - name: 'webhook' + webhook_configs: + - url: 'http://${hertzbeat_host}:1157/api/alerts/report/alertmanager' + http_config: + headers: + Authorization: 'Bearer {token}' + send_resolved: true + ``` +- `http://${hertzbeat_ip}:8080/api/alerts/report` 为 HertzBeat 提供的 webhook 接口地址。 +- `send_resolved: true` 表示发送告警恢复信息。 +- `Authorization` 内的 {token} 为 HertzBeat 提供的 token。 + +2. 重启 Alertmanager 服务。 + +### 配置验证 + +- 触发 Prometheus AlertManager 告警。 +- 在 HertzBeat 告警平台中对告警数据处理查看,验证告警数据是否正确。 + +### 数据流转: + +```mermaid +graph LR + A[Prometheus Alertmanager] --> B[Webhook] + B --> C[HertzBeat告警平台] + C --> D[分组收敛] + D --> E[告警抑制] + E --> F[告警静默] + F --> G[告警中心] + F --> H[消息分发] +``` + +### 常见问题 + +- 确保 Alertmanager 配置文件中的 webhook 地址正确,且网络通畅。 +- 检查 Alertmanager 的告警是否触发,是否发送到 HertzBeat 告警平台。 diff --git a/web-app/src/assets/doc/alert-integration/alertmanager.zh-TW.md b/web-app/src/assets/doc/alert-integration/alertmanager.zh-TW.md new file mode 100644 index 00000000000..b7606af054f --- /dev/null +++ b/web-app/src/assets/doc/alert-integration/alertmanager.zh-TW.md @@ -0,0 +1,44 @@ +> 將 Prometheus AlertManager 的告警發送到 HertzBeat 告警平台。 + +### Alertmanager 配置 Webhook + +1. 在 Alertmanager 配置文件中添加 webhook 配置。 + + ```yaml + receivers: + - name: 'webhook' + webhook_configs: + - url: 'http://${hertzbeat_host}:1157/api/alerts/report/alertmanager' + http_config: + headers: + Authorization: 'Bearer {token}' + send_resolved: true + ``` +- `http://${hertzbeat_ip}:8080/api/alerts/report` 為 HertzBeat 提供的 webhook 接口地址。 +- `send_resolved: true` 表示發送告警恢復信息。 +- `Authorization` 內的 {token} 為 HertzBeat 提供的 token。 + +2. 重啟 Alertmanager 服務。 + +### 配置驗證 + +- 觸發 Prometheus AlertManager 告警。 +- 在 HertzBeat 告警平台中對告警數據處理查看,驗證告警數據是否正確。 + +### 數據流轉: + +```mermaid +graph LR + A[Prometheus Alertmanager] --> B[Webhook] + B --> C[HertzBeat告警平台] + C --> D[分組收斂] + D --> E[告警抑制] + E --> F[告警靜默] + F --> G[告警中心] + F --> H[消息分發] +``` + +### 常見問題 + +- 確保 Alertmanager 配置文件中的 webhook 地址正確,且網絡通暢。 +- 檢查 Alertmanager 的告警是否觸發,是否發送到 HertzBeat 告警平台。 diff --git a/web-app/src/assets/doc/alert-integration/prometheus.en-US.md b/web-app/src/assets/doc/alert-integration/prometheus.en-US.md new file mode 100644 index 00000000000..5e6f669ac46 --- /dev/null +++ b/web-app/src/assets/doc/alert-integration/prometheus.en-US.md @@ -0,0 +1,78 @@ +# Prometheus Alert Integration + +HertzBeat is fully compatible with Prometheus alert data format. You can configure Prometheus alerting rules to send alerts to HertzBeat. + +## Prometheus Alert Configuration + +> Since Prometheus Server itself doesn't support sending alerts via HTTP API, external scripts or Alertmanager are needed to implement alert sending. +> If using Alertmanager, please refer to the **Alertmanager Integration Documentation**. Here we provide the alert configuration method for Prometheus Server without deploying Alertmanager. + +### Prometheus Alert Configuration + +1. Edit Prometheus configuration file `prometheus.yml`, add alert rules configuration + ```yaml + rule_files: + - "rules/*.rules.yml" + ``` + > `rules/*.rules.yml` is the path to alert rule files, which can be modified according to actual situations +> 2. Create alert rules folder `rules` and create alert rule files `rules/*.rules.yml` +> 3. Edit alert rule files, add alert rule configurations +> 4. Reload Prometheus configuration + +### Write Scripts to Send Alerts Automatically + +> Since Prometheus Server itself doesn't support sending alerts via HTTP API, we'll use Python scripts to implement alert sending. + +1. Install Python requests library + ```bash + pip install requests + ``` +2. Write Python script `send_alerts.py` +```python +import requests + +PROMETHEUS_URL = "http://:9090/api/v1/alerts" +WEBHOOK_URL = "http://:1157/api/alerts/report/prometheus" + +def get_prometheus_alerts(): + response = requests.get(PROMETHEUS_URL) + alerts = response.json()["data"]["alerts"] + return alerts + +def send_to_webhook(alert): + requests.post(WEBHOOK_URL, json=alert) + +if __name__ == "__main__": + while True: + alerts = get_prometheus_alerts() + for alert in alerts: + send_to_webhook(alert) + # schedule cyclic task, every 300s once + time.sleep(300) + +``` +3. Run Python script + ```bash + python send_alerts.py + ``` + > This script will fetch alert data from Prometheus Server and push it to HertzBeat alert platform via Webhook. + +## Verify Configuration + +1. Ensure Prometheus configuration is correct and reload configuration + ```bash + curl -X POST http://localhost:9090/-/reload + ``` +2. Check Prometheus alert rules status + ```bash + curl http://localhost:9090/api/v1/rules + ``` +3. Trigger test alerts and check in HertzBeat alert center + +## Common Issues + +- Ensure HertzBeat URL is accessible from Prometheus server +- Check Prometheus logs for alert sending failure error messages +- Verify the correctness of alert rule expressions + +For more information, please refer to [Prometheus Alerting Documentation](https://prometheus.io/docs/alerting/latest/configuration/) diff --git a/web-app/src/assets/doc/alert-integration/prometheus.zh-CN.md b/web-app/src/assets/doc/alert-integration/prometheus.zh-CN.md new file mode 100644 index 00000000000..498d3c36d63 --- /dev/null +++ b/web-app/src/assets/doc/alert-integration/prometheus.zh-CN.md @@ -0,0 +1,72 @@ +> 由于 Prometheus Server 本身并不支持 HTTP API 的告警发送,因此需要借助外部脚本或者 Alertmanager 来实现告警发送。 +> 若使用 Alertmanager,可参考 **Alertmanager 集成文档**。这里提供非部署 Alertmanager 的 Prometheus Server 的告警配置方法。 + +### Prometheus 告警配置 + +1. 編輯 Prometheus 配置文件 `prometheus.yml`,添加告警規則配置 + ```yaml + rule_files: + - "rules/*.rules.yml" + ``` + > `rules/*.rules.yml` 為告警規則文件路徑,可以根據實際情況修改 +> 2. 創建告警規則文件夾 `rules`,並創建告警規則文件 `rules/*.rules.yml` +> 3. 編輯告警規則文件,添加告警規則配置 +> 4. 重新加載 Prometheus 配置 + +### 编写脚本自动发送告警 + +> 由于 Prometheus Server 本身并不支持 HTTP API 的告警发送,这里我们使用 Python 脚本来实现告警发送。 + +1. 安装 Python requests 库 + ```bash + pip install requests + ``` +2. 编写 Python 脚本 `send_alerts.py` +```python +import requests + +PROMETHEUS_URL = "http://:9090/api/v1/alerts" +WEBHOOK_URL = "http://:1157/api/alerts/report/prometheus" + +def get_prometheus_alerts(): + response = requests.get(PROMETHEUS_URL) + alerts = response.json()["data"]["alerts"] + return alerts + +def send_to_webhook(alert): + requests.post(WEBHOOK_URL, json=alert) + +if __name__ == "__main__": + while True: + alerts = get_prometheus_alerts() + for alert in alerts: + send_to_webhook(alert) + # 设置定时任务,例如每 300 秒即 5 分钟执行一次 + time.sleep(300) + +``` +3. 运行 Python 脚本 + ```bash + python send_alerts.py + ``` + > 该脚本会从 Prometheus Server 获取告警数据,并通过 Webhook 推送到 HertzBeat 告警平台。 + +## 验证配置 + +1. 确保 Prometheus 配置正确并重新加载配置 + ```bash + curl -X POST http://localhost:9090/-/reload + ``` +2. 检查 Prometheus 告警规则状态 + ```bash + curl http://localhost:9090/api/v1/rules + ``` +3. 触发测试告警并在 HertzBeat 告警中心查看 + +## 常见问题 + +- 确保 HertzBeat URL 可以被 Prometheus 服务器访问 +- 检查 Prometheus 日志中是否有告警发送失败的错误信息 +- 验证告警规则表达式的正确性 + +更多信息請參考 [Prometheus 告警配置文檔](https://prometheus.io/docs/alerting/latest/configuration/) diff --git a/web-app/src/assets/doc/alert-integration/prometheus.zh-TW.md b/web-app/src/assets/doc/alert-integration/prometheus.zh-TW.md new file mode 100644 index 00000000000..7dcf5b57aec --- /dev/null +++ b/web-app/src/assets/doc/alert-integration/prometheus.zh-TW.md @@ -0,0 +1,72 @@ +> 由於 Prometheus Server 本身並不支持 HTTP API 的告警發送,因此需要借助外部腳本或者 Alertmanager 來實現告警發送。 +> 若使用 Alertmanager,可參考 **Alertmanager 集成文檔**。這裡提供非部署 Alertmanager 的 Prometheus Server 的告警配置方法。 + +### Prometheus 告警配置 + +1. 編輯 Prometheus 配置文件 `prometheus.yml`,添加告警規則配置 + ```yaml + rule_files: + - "rules/*.rules.yml" + ``` + > `rules/*.rules.yml` 為告警規則文件路徑,可以根據實際情況修改 +> 2. 創建告警規則文件夾 `rules`,並創建告警規則文件 `rules/*.rules.yml` +> 3. 編輯告警規則文件,添加告警規則配置 +> 4. 重新加載 Prometheus 配置 + +### 編寫腳本自動發送告警 + +> 由於 Prometheus Server 本身並不支持 HTTP API 的告警發送,這裡我們使用 Python 腳本來實現告警發送。 + +1. 安裝 Python requests 庫 + ```bash + pip install requests + ``` +2. 編寫 Python 腳本 `send_alerts.py` +```python +import requests + +PROMETHEUS_URL = "http://:9090/api/v1/alerts" +WEBHOOK_URL = "http://:1157/api/alerts/report/prometheus" + +def get_prometheus_alerts(): + response = requests.get(PROMETHEUS_URL) + alerts = response.json()["data"]["alerts"] + return alerts + +def send_to_webhook(alert): + requests.post(WEBHOOK_URL, json=alert) + +if __name__ == "__main__": + while True: + alerts = get_prometheus_alerts() + for alert in alerts: + send_to_webhook(alert) + # 设置定时任务,例如每 300 秒即 5 分钟执行一次 + time.sleep(300) + +``` +3. 運行 Python 腳本 + ```bash + python send_alerts.py + ``` + > 該腳本會從 Prometheus Server 獲取告警數據,並通過 Webhook 推送到 HertzBeat 告警平台。 + +## 驗證配置 + +1. 確保 Prometheus 配置正確並重新加載配置 + ```bash + curl -X POST http://localhost:9090/-/reload + ``` +2. 檢查 Prometheus 告警規則狀態 + ```bash + curl http://localhost:9090/api/v1/rules + ``` +3. 觸發測試告警並在 HertzBeat 告警中心查看 + +## 常見問題 + +- 確保 HertzBeat URL 可以被 Prometheus 服務器訪問 +- 檢查 Prometheus 日誌中是否有告警發送失敗的錯誤信息 +- 驗證告警規則表達式的正確性 + +更多信息請參考 [Prometheus 告警配置文檔](https://prometheus.io/docs/alerting/latest/configuration/) diff --git a/web-app/src/assets/doc/alert-integration/tencent.en-US.md b/web-app/src/assets/doc/alert-integration/tencent.en-US.md new file mode 100644 index 00000000000..e69de29bb2d diff --git a/web-app/src/assets/doc/alert-integration/tencent.zh-CN.md b/web-app/src/assets/doc/alert-integration/tencent.zh-CN.md new file mode 100644 index 00000000000..e69de29bb2d diff --git a/web-app/src/assets/doc/alert-integration/tencent.zh-TW.md b/web-app/src/assets/doc/alert-integration/tencent.zh-TW.md new file mode 100644 index 00000000000..a607d164c7a --- /dev/null +++ b/web-app/src/assets/doc/alert-integration/tencent.zh-TW.md @@ -0,0 +1,9 @@ +## 验证配置 + +1. 确保 Prometheus 配置正确并重新加载配置 +2. 触发一个测试告警 +3. 在 HertzBeat 告警中心查看是否收到告警 + +更多信息请参考 [Prometheus 官方文档](https://prometheus.io/docs/alerting/latest/configuration/) + +## Alert Rule Example diff --git a/web-app/src/assets/doc/alert-integration/webhook.en-US.md b/web-app/src/assets/doc/alert-integration/webhook.en-US.md new file mode 100644 index 00000000000..f0748d18ba9 --- /dev/null +++ b/web-app/src/assets/doc/alert-integration/webhook.en-US.md @@ -0,0 +1,70 @@ +> HertzBeat provides an external API interface that allows external systems to push alert data to the HertzBeat alert platform via Webhook. + +### API Endpoint + +`POST /api/alerts/report` + +### Request Headers + +- `Content-Type`: `application/json` +- `Authorization`: `Bearer ${token}` + +### Request Body + +```json +{ + "labels": { + "alertname": "HighCPUUsage", + "priority": "critical", + "instance": "343483943" + }, + "annotations": { + "summary": "High CPU usage detected" + }, + "content": "The CPU usage on instance 343483943 is critically high.", + "status": "firing", + "triggerTimes": 3, + "startAt": 1736580031832, + "activeAt": 1736580039832, + "endAt": null +} +``` + +Field Description + +- `labels`: Alert labels + - `alertname`: Name of the alert rule + - `priority`: Alert priority (warning, critical) + - `instance`: Alert instance +- `annotations`: Alert annotation information + - `summary`: Alert summary + - `description`: Detailed description of the alert +- `content`: Alert content +- `status`: Alert status (firing, resolved) +- `triggerTimes`: Number of times the alert was triggered +- `startAt`: Start time of the alert +- `activeAt`: Time when the alert became active +- `endAt`: End time of the alert (if resolved) + +### Configuration Verification + +- After the third-party system triggers an alert, it calls HertzBeat's `/api/alerts/report` interface via webhook to push alert data to the HertzBeat alert platform. +- Check the alert data processing in the HertzBeat alert platform to verify if the alert data is correct. + +### Data Flow: + +```mermaid +graph LR + A[External System Alert] --> B[Webhook] + B --> C[HertzBeat Alert Platform] + C --> D[Group Convergence] + D --> E[Alert Suppression] + E --> F[Alert Silence] + F --> G[Alert Center] + F --> H[Message Distribution] +``` + +### Common Issues + +- Ensure the HertzBeat URL is accessible from the third-party system server. +- Check the logs of the third-party system for messages indicating whether the alert was successfully sent or failed. diff --git a/web-app/src/assets/doc/alert-integration/webhook.zh-CN.md b/web-app/src/assets/doc/alert-integration/webhook.zh-CN.md new file mode 100644 index 00000000000..53ebbfbc552 --- /dev/null +++ b/web-app/src/assets/doc/alert-integration/webhook.zh-CN.md @@ -0,0 +1,73 @@ +> HertzBeat 对外提供 api 接口,外部系统可以通过 Webhook 方式调用此接口将告警数据推送到 HertzBeat 告警平台。 + +### 接口端点 + +`POST /api/alerts/report` + +### 请求头 + +- `Content-Type`: `application/json` +- `Authorization`: `Bearer ${token}` + +### 请求体 + +```json +{ + "labels": { + "alertname": "HighCPUUsage", + "priority": "critical", + "instance": "343483943" + }, + "annotations": { + "summary": "High CPU usage detected" + }, + "content": "The CPU usage on instance 343483943 is critically high.", + "status": "firing", + "triggerTimes": 3, + "startAt": 1736580031832, + "activeAt": 1736580039832, + "endAt": null +} +``` + +字段說明 + +- `labels`: 告警標籤 + - `alertname`: 告警規則名稱 + - `priority`: 告警級別 (warning, critical) + - `instance`: 告警實例 +- `annotations`: 告警註釋信息 + - `summary`: 告警摘要 + - `description`: 告警詳細描述 +- `content`: 告警內容 +- `status`: 告警狀態 (firing, resolved) +- `triggerTimes`: 告警觸發次數 +- `startAt`: 告警開始時間 +- `activeAt`: 告警激活時間 +- `endAt`: 告警結束時間 + + +### 配置验证 + +- 第三方系统触发告警后通过 webhook 回调 HertzBeat 的 `/api/alerts/report` 接口,将告警数据推送到 HertzBeat 告警平台。 +- 在 HertzBeat 告警平台中对告警数据处理查看,验证告警数据是否正确。 + + +### 数据流转: + +```mermaid +graph LR + A[外部系统告警] --> B[Webhook] + B --> C[HertzBeat告警平台] + C --> D[分组收敛] + D --> E[告警抑制] + E --> F[告警静默] + F --> G[告警中心] + F --> H[消息分发] +``` + + +### 常见问题 + +- 确保 HertzBeat URL 可以被第三方系统服务器访问。 +- 检查第三方系统日志中是否有告警发送成功失败的消息。 diff --git a/web-app/src/assets/doc/alert-integration/webhook.zh-TW.md b/web-app/src/assets/doc/alert-integration/webhook.zh-TW.md new file mode 100644 index 00000000000..873dfbfda87 --- /dev/null +++ b/web-app/src/assets/doc/alert-integration/webhook.zh-TW.md @@ -0,0 +1,70 @@ +> HertzBeat 對外提供 API 接口,外部系統可以通過 Webhook 方式調用此接口將告警數據推送到 HertzBeat 告警平台。 + +### 接口端點 + +`POST /api/alerts/report` + +### 請求頭 + +- `Content-Type`: `application/json` +- `Authorization`: `Bearer ${token}` + +### 請求體 + +```json +{ + "labels": { + "alertname": "HighCPUUsage", + "priority": "critical", + "instance": "343483943" + }, + "annotations": { + "summary": "檢測到高 CPU 使用率" + }, + "content": "實例 343483943 的 CPU 使用率極高。", + "status": "firing", + "triggerTimes": 3, + "startAt": 1736580031832, + "activeAt": 1736580039832, + "endAt": null +} +``` + +字段說明 + +- `labels`: 告警標籤 + - `alertname`: 告警規則名稱 + - `priority`: 告警級別 (warning, critical) + - `instance`: 告警實例 +- `annotations`: 告警註釋信息 + - `summary`: 告警摘要 + - `description`: 告警詳細描述 +- `content`: 告警內容 +- `status`: 告警狀態 (firing, resolved) +- `triggerTimes`: 告警觸發次數 +- `startAt`: 告警開始時間 +- `activeAt`: 告警激活時間 +- `endAt`: 告警結束時間 + +### 配置驗證 + +- 第三方系統觸發告警後通過 webhook 回調 HertzBeat 的 `/api/alerts/report` 接口,將告警數據推送到 HertzBeat 告警平台。 +- 在 HertzBeat 告警平台中對告警數據處理查看,驗證告警數據是否正確。 + +### 數據流轉: + +```mermaid +graph LR + A[外部系統告警] --> B[Webhook] + B --> C[HertzBeat告警平台] + C --> D[分組收斂] + D --> E[告警抑制] + E --> F[告警靜默] + F --> G[告警中心] + F --> H[消息分發] +``` + +### 常見問題 + +- 確保 HertzBeat URL 可以被第三方系統服務器訪問。 +- 檢查第三方系統日誌中是否有告警發送成功失敗的消息。 diff --git a/web-app/src/assets/i18n/en-US.json b/web-app/src/assets/i18n/en-US.json index ef8b40534dd..0e01eda1202 100644 --- a/web-app/src/assets/i18n/en-US.json +++ b/web-app/src/assets/i18n/en-US.json @@ -9,7 +9,7 @@ "clear.local.storage": "Clear Local Storage", "monitor": { "": "Monitoring", - "center": "Monitor Center", + "center": "Monitors", "bulletin": "Bulletin", "service": "Service Monitor", "db": "DB Monitor", @@ -38,25 +38,26 @@ }, "alert": { "": "Alerting", - "center": "Alarm Center", - "group": "Group Converge", - "converge": "Alarm Converge", - "inhibit": "Alarm Inhibit", - "setting": "Threshold Rule", - "silence": "Alarm Silence", - "dispatch": "Notification" + "center": "Alarms", + "group": "Group", + "converge": "Converge", + "inhibit": "Inhibit", + "setting": "Threshold", + "silence": "Silence", + "dispatch": "Notification", + "integration": "Integration" }, "advanced": { "": "Advanced", - "collector": "Collector Cluster", - "labels": "Labels Manage", - "define": "Monitor Template", - "status": "Status Page", - "plugins": "Plugins Manage" + "collector": "Collector", + "labels": "Labels", + "define": "Template", + "status": "Status", + "plugins": "Plugins" }, "extras": { "": "More", - "help": "Help Center", + "help": "Help", "setting": "Setting", "settings": "Settings", "about": "About" @@ -274,6 +275,8 @@ "alert.help.setting.link": "https://hertzbeat.apache.org/docs/help/alert_threshold", "alert.help.silence": "Alarm Silence management is used when you don’t want to be disturbed during system maintenance or on nights weekend.
Click \"New Silence Strategy\" and configure the time period to block messages so you would not get disturbed during breaks.", "alert.help.silence.link": "https://hertzbeat.apache.org/docs", + "alert.help.integration": "Unified management of alerts from different third-party platforms, integrating and receiving alert messages from third-party monitoring and observability systems, and performing actions such as grouping, aggregation, inhibition, silencing, and notification distribution.", + "alert.help.integration.link": "https://hertzbeat.apache.org", "alert.notice.template": "Notice Template", "alert.notice.template.new": "New Template", "alert.notice.template.edit": "Edit Template", @@ -374,6 +377,15 @@ "alert.notice.sender.sms.tencent.templateId": "Tencent Sms TemplateId", "alert.export.switch-type": "Please select the export file format!", "alert.export.use-type": "Export rules in {{type}} file format", + "alert.integration.source": "Integration Source", + "alert.integration.source.webhook": "Default Webhook", + "alert.integration.source.prometheus": "Prometheus", + "alert.integration.source.alertmanager": "Alertmanager", + "alert.integration.source.tencent": "Tencent Cloud", + "alert.integration.token.new": "Click to Generate Token", + "alert.integration.token.desc": "Token you generated that can be used to access the HertzBeat API.", + "alert.integration.token.title": "Access Token", + "alert.integration.token.notice": "Token only be displayed once. Please keep your token secure. Do not share it with others.", "dashboard.alerts.title": "Recently Alarms List", "dashboard.alerts.title-no": "Recently Pending Alarms", "dashboard.alerts.no": "No Pending Alarms", diff --git a/web-app/src/assets/i18n/zh-CN.json b/web-app/src/assets/i18n/zh-CN.json index 5752eebfdf2..2b96a4e8d2a 100644 --- a/web-app/src/assets/i18n/zh-CN.json +++ b/web-app/src/assets/i18n/zh-CN.json @@ -43,7 +43,8 @@ "inhibit": "告警抑制", "silence": "告警静默", "setting": "阈值规则", - "dispatch": "消息通知" + "dispatch": "消息通知", + "integration": "集成接入" }, "advanced": { "": "高级", @@ -275,6 +276,8 @@ "alert.help.setting.link": "https://hertzbeat.apache.org/zh-cn/docs/help/alert_threshold", "alert.help.silence": "告警静默管理用于您在系统维护期间或夜晚周末不想受到告警打扰时,可以点击”新增静默策略“,设置指定时间段内屏蔽告警通知。
告警静默规则支持一次性时间段或周期性时间段,支持标签匹配和告警级别匹配部分告警。", "alert.help.silence.link":"https://hertzbeat.apache.org/zh-cn/docs/#%E5%91%8A%E8%AD%A6%E9%9D%99%E9%BB%98", + "alert.help.integration": "统一管理不同第三方平台告警,集成接入第三方监控观测系统的告警消息,对其进行分组,收敛,抑制,静默,分发通知等。", + "alert.help.integration.link": "https://hertzbeat.apache.org", "alert.notice.template": "通知模板", "alert.notice.template.new": "新增通知模板", "alert.notice.template.edit": "编辑通知模板", @@ -376,6 +379,15 @@ "alert.notice.sender.sms.tencent.templateId": "腾讯短信TemplateId", "alert.export.switch-type": "请选择导出文件格式!", "alert.export.use-type": "以 {{type}} 文件格式导出阈值规则", + "alert.integration.source": "集成告警源", + "alert.integration.source.webhook": "默认Webhook", + "alert.integration.source.prometheus": "Prometheus", + "alert.integration.source.alertmanager": "Alertmanager", + "alert.integration.source.tencent": "腾讯云监控", + "alert.integration.token.new": "点击生成 Token", + "alert.integration.token.desc": "生成的 Token 可用于访问 HertzBeat API", + "alert.integration.token.title": "访问认证 Token", + "alert.integration.token.notice": "此内容只会展示一次,请妥善保管您的 Token,不要泄露给他人", "dashboard.alerts.title": "最近告警列表", "dashboard.alerts.title-no": "最近未处理告警", "dashboard.alerts.no": "暂无未处理告警", diff --git a/web-app/src/assets/i18n/zh-TW.json b/web-app/src/assets/i18n/zh-TW.json index 068b814700f..183c857b223 100644 --- a/web-app/src/assets/i18n/zh-TW.json +++ b/web-app/src/assets/i18n/zh-TW.json @@ -44,7 +44,8 @@ "converge": "告警收斂", "inhibit": "告警抑制", "silence": "告警靜默", - "dispatch": "消息通知" + "dispatch": "消息通知", + "integration": "集成接入" }, "bulletin": { "new": "新增看板項", @@ -287,6 +288,8 @@ "alert.help.setting.link": "https://hertzbeat.apache.org/zh-cn/docs/help/alert_threshold", "alert.help.silence": "告警靜默管理用于您在系統維護期間或夜晚周末不想受到告警打擾時,可以點擊”新增靜默策略“,設置指定時間段內屏蔽告警通知。
告警靜默規則支持壹次性時間段或周期性時間段,支持標簽匹配和告警級別匹配部分告警。", "alert.help.silence.link": "https://hertzbeat.apache.org/zh-cn/docs/#%E5%91%8A%E8%AD%A6%E9%9D%99%E9%BB%98", + "alert.help.integration": "统一管理不同第三方平台告警,集成接入第三方监控观测系统的告警消息,对其进行分组,收敛,抑制,静默,分发通知等。", + "alert.help.integration.link": "https://hertzbeat.apache.org", "alert.notice.template": "通知模板", "alert.notice.template.new": "新增通知模板", "alert.notice.template.edit": "編輯通知模板", @@ -388,6 +391,15 @@ "alert.notice.sender.sms.tencent.templateId": "騰訊短訊TemplateId", "alert.export.switch-type": "請選擇導出文件格式!", "alert.export.use-type": "以 {{type}} 文件格式導出阈值規則", + "alert.integration.source": "集成告警源", + "alert.integration.source.webhook": "默认Webhook", + "alert.integration.source.prometheus": "Prometheus", + "alert.integration.source.alertmanager": "Alertmanager", + "alert.integration.source.tencent": "腾讯云监控", + "alert.integration.token.new": "点击生成 Token", + "alert.integration.token.desc": "生成的 Token 可用于访问 HertzBeat API", + "alert.integration.token.title": "访问认证 Token", + "alert.integration.token.notice": "此内容只会展示一次,请妥善保管您的 Token,不要泄露给他人", "dashboard.alerts.title": "最近告警列表", "dashboard.alerts.title-no": "最近未處理告警", "dashboard.alerts.no": "暫無未處理告警", diff --git a/web-app/src/assets/img/integration/prometheus.svg b/web-app/src/assets/img/integration/prometheus.svg new file mode 100644 index 00000000000..6dd1212f3ad --- /dev/null +++ b/web-app/src/assets/img/integration/prometheus.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web-app/src/assets/img/integration/tencent.svg b/web-app/src/assets/img/integration/tencent.svg new file mode 100644 index 00000000000..46d45b869bc --- /dev/null +++ b/web-app/src/assets/img/integration/tencent.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web-app/yarn.lock b/web-app/yarn.lock index fa288a7e96a..14f5b100b06 100644 --- a/web-app/yarn.lock +++ b/web-app/yarn.lock @@ -314,6 +314,19 @@ "@ant-design/colors" "^7.0.0" tslib "^2.0.0" +"@antfu/install-pkg@^0.4.1": + version "0.4.1" + resolved "https://registry.npmmirror.com/@antfu/install-pkg/-/install-pkg-0.4.1.tgz#d1d7f3be96ecdb41581629cafe8626d1748c0cf1" + integrity sha512-T7yB5QNG29afhWVkVq7XeIMBa5U/vs9mX69YqayXypPRmYzUmzwnYltplHmPtZ4HPCn+sQKeXW8I47wCbuBOjw== + dependencies: + package-manager-detector "^0.2.0" + tinyexec "^0.3.0" + +"@antfu/utils@^0.7.10": + version "0.7.10" + resolved "https://registry.npmmirror.com/@antfu/utils/-/utils-0.7.10.tgz#ae829f170158e297a9b6a28f161a8e487d00814d" + integrity sha512-+562v9k4aI80m1+VuMHehNJWLOFjBnXn3tdOitzD0il5b7smkSBal4+a3oKiQTbrwMmN/TBUMDvbdoWDehgOww== + "@babel/code-frame@^7.0.0", "@babel/code-frame@^7.23.5", "@babel/code-frame@^7.24.7": version "7.24.7" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.24.7.tgz#882fd9e09e8ee324e496bd040401c6f046ef4465" @@ -1368,6 +1381,43 @@ "@babel/helper-validator-identifier" "^7.24.7" to-fast-properties "^2.0.0" +"@braintree/sanitize-url@^7.0.1": + version "7.1.1" + resolved "https://registry.npmmirror.com/@braintree/sanitize-url/-/sanitize-url-7.1.1.tgz#15e19737d946559289b915e5dad3b4c28407735e" + integrity sha512-i1L7noDNxtFyL5DmZafWy1wRVhGehQmzZaz1HiN5e7iylJMSZR7ekOV7NsIqa5qBldlLrsKv4HbgFUVlQrz8Mw== + +"@chevrotain/cst-dts-gen@11.0.3": + version "11.0.3" + resolved "https://registry.npmmirror.com/@chevrotain/cst-dts-gen/-/cst-dts-gen-11.0.3.tgz#5e0863cc57dc45e204ccfee6303225d15d9d4783" + integrity sha512-BvIKpRLeS/8UbfxXxgC33xOumsacaeCKAjAeLyOn7Pcp95HiRbrpl14S+9vaZLolnbssPIUuiUd8IvgkRyt6NQ== + dependencies: + "@chevrotain/gast" "11.0.3" + "@chevrotain/types" "11.0.3" + lodash-es "4.17.21" + +"@chevrotain/gast@11.0.3": + version "11.0.3" + resolved "https://registry.npmmirror.com/@chevrotain/gast/-/gast-11.0.3.tgz#e84d8880323fe8cbe792ef69ce3ffd43a936e818" + integrity sha512-+qNfcoNk70PyS/uxmj3li5NiECO+2YKZZQMbmjTqRI3Qchu8Hig/Q9vgkHpI3alNjr7M+a2St5pw5w5F6NL5/Q== + dependencies: + "@chevrotain/types" "11.0.3" + lodash-es "4.17.21" + +"@chevrotain/regexp-to-ast@11.0.3": + version "11.0.3" + resolved "https://registry.npmmirror.com/@chevrotain/regexp-to-ast/-/regexp-to-ast-11.0.3.tgz#11429a81c74a8e6a829271ce02fc66166d56dcdb" + integrity sha512-1fMHaBZxLFvWI067AVbGJav1eRY7N8DDvYCTwGBiE/ytKBgP8azTdgyrKyWZ9Mfh09eHWb5PgTSO8wi7U824RA== + +"@chevrotain/types@11.0.3": + version "11.0.3" + resolved "https://registry.npmmirror.com/@chevrotain/types/-/types-11.0.3.tgz#f8a03914f7b937f594f56eb89312b3b8f1c91848" + integrity sha512-gsiM3G8b58kZC2HaWR50gu6Y1440cHiJ+i3JUvcp/35JchYejb2+5MVeJK0iKThYpAa/P2PYFV4hoi44HD+aHQ== + +"@chevrotain/utils@11.0.3": + version "11.0.3" + resolved "https://registry.npmmirror.com/@chevrotain/utils/-/utils-11.0.3.tgz#e39999307b102cff3645ec4f5b3665f5297a2224" + integrity sha512-YslZMgtJUyuMbZ+aKvfF3x1f5liK4mWNxghFRv7jqRR9C3R3fAOGTTKvxXDa2Y1s9zSbcpuO0cAxDYsc9SrXoQ== + "@colors/colors@1.5.0": version "1.5.0" resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9" @@ -1827,6 +1877,25 @@ resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz#4a2868d75d6d6963e423bcf90b7fd1be343409d3" integrity sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA== +"@iconify/types@^2.0.0": + version "2.0.0" + resolved "https://registry.npmmirror.com/@iconify/types/-/types-2.0.0.tgz#ab0e9ea681d6c8a1214f30cd741fe3a20cc57f57" + integrity sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg== + +"@iconify/utils@^2.1.32": + version "2.2.1" + resolved "https://registry.npmmirror.com/@iconify/utils/-/utils-2.2.1.tgz#635b9bd8fd3e5e53742471bc0b5291f1570dda41" + integrity sha512-0/7J7hk4PqXmxo5PDBDxmnecw5PxklZJfNjIVG9FM0mEfVrvfudS22rYWsqVk6gR3UJ/mSYS90X4R3znXnqfNA== + dependencies: + "@antfu/install-pkg" "^0.4.1" + "@antfu/utils" "^0.7.10" + "@iconify/types" "^2.0.0" + debug "^4.4.0" + globals "^15.13.0" + kolorist "^1.8.0" + local-pkg "^0.5.1" + mlly "^1.7.3" + "@isaacs/cliui@^8.0.2": version "8.0.2" resolved "https://registry.yarnpkg.com/@isaacs/cliui/-/cliui-8.0.2.tgz#b37667b7bc181c168782259bab42474fbf52b550" @@ -1929,6 +1998,13 @@ dependencies: call-bind "^1.0.7" +"@mermaid-js/parser@^0.3.0": + version "0.3.0" + resolved "https://registry.npmmirror.com/@mermaid-js/parser/-/parser-0.3.0.tgz#7a28714599f692f93df130b299fa1aadc9f9c8ab" + integrity sha512-HsvL6zgE5sUPGgkIDlmAWR1HTNHz2Iy11BAWPTa4Jjabkpguy4Ze2gzfLrg6pdRuBvFwgUYyxiaNqZwrEEXepA== + dependencies: + langium "3.0.0" + "@mrmlnc/readdir-enhanced@^2.2.1": version "2.2.1" resolved "https://registry.yarnpkg.com/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz#524af240d1a360527b730475ecfa1344aa540dde" @@ -2371,6 +2447,216 @@ dependencies: "@types/node" "*" +"@types/d3-array@*": + version "3.2.1" + resolved "https://registry.npmmirror.com/@types/d3-array/-/d3-array-3.2.1.tgz#1f6658e3d2006c4fceac53fde464166859f8b8c5" + integrity sha512-Y2Jn2idRrLzUfAKV2LyRImR+y4oa2AntrgID95SHJxuMUrkNXmanDSed71sRNZysveJVt1hLLemQZIady0FpEg== + +"@types/d3-axis@*": + version "3.0.6" + resolved "https://registry.npmmirror.com/@types/d3-axis/-/d3-axis-3.0.6.tgz#e760e5765b8188b1defa32bc8bb6062f81e4c795" + integrity sha512-pYeijfZuBd87T0hGn0FO1vQ/cgLk6E1ALJjfkC0oJ8cbwkZl3TpgS8bVBLZN+2jjGgg38epgxb2zmoGtSfvgMw== + dependencies: + "@types/d3-selection" "*" + +"@types/d3-brush@*": + version "3.0.6" + resolved "https://registry.npmmirror.com/@types/d3-brush/-/d3-brush-3.0.6.tgz#c2f4362b045d472e1b186cdbec329ba52bdaee6c" + integrity sha512-nH60IZNNxEcrh6L1ZSMNA28rj27ut/2ZmI3r96Zd+1jrZD++zD3LsMIjWlvg4AYrHn/Pqz4CF3veCxGjtbqt7A== + dependencies: + "@types/d3-selection" "*" + +"@types/d3-chord@*": + version "3.0.6" + resolved "https://registry.npmmirror.com/@types/d3-chord/-/d3-chord-3.0.6.tgz#1706ca40cf7ea59a0add8f4456efff8f8775793d" + integrity sha512-LFYWWd8nwfwEmTZG9PfQxd17HbNPksHBiJHaKuY1XeqscXacsS2tyoo6OdRsjf+NQYeB6XrNL3a25E3gH69lcg== + +"@types/d3-color@*": + version "3.1.3" + resolved "https://registry.npmmirror.com/@types/d3-color/-/d3-color-3.1.3.tgz#368c961a18de721da8200e80bf3943fb53136af2" + integrity sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A== + +"@types/d3-contour@*": + version "3.0.6" + resolved "https://registry.npmmirror.com/@types/d3-contour/-/d3-contour-3.0.6.tgz#9ada3fa9c4d00e3a5093fed0356c7ab929604231" + integrity sha512-BjzLgXGnCWjUSYGfH1cpdo41/hgdWETu4YxpezoztawmqsvCeep+8QGfiY6YbDvfgHz/DkjeIkkZVJavB4a3rg== + dependencies: + "@types/d3-array" "*" + "@types/geojson" "*" + +"@types/d3-delaunay@*": + version "6.0.4" + resolved "https://registry.npmmirror.com/@types/d3-delaunay/-/d3-delaunay-6.0.4.tgz#185c1a80cc807fdda2a3fe960f7c11c4a27952e1" + integrity sha512-ZMaSKu4THYCU6sV64Lhg6qjf1orxBthaC161plr5KuPHo3CNm8DTHiLw/5Eq2b6TsNP0W0iJrUOFscY6Q450Hw== + +"@types/d3-dispatch@*": + version "3.0.6" + resolved "https://registry.npmmirror.com/@types/d3-dispatch/-/d3-dispatch-3.0.6.tgz#096efdf55eb97480e3f5621ff9a8da552f0961e7" + integrity sha512-4fvZhzMeeuBJYZXRXrRIQnvUYfyXwYmLsdiN7XXmVNQKKw1cM8a5WdID0g1hVFZDqT9ZqZEY5pD44p24VS7iZQ== + +"@types/d3-drag@*": + version "3.0.7" + resolved "https://registry.npmmirror.com/@types/d3-drag/-/d3-drag-3.0.7.tgz#b13aba8b2442b4068c9a9e6d1d82f8bcea77fc02" + integrity sha512-HE3jVKlzU9AaMazNufooRJ5ZpWmLIoc90A37WU2JMmeq28w1FQqCZswHZ3xR+SuxYftzHq6WU6KJHvqxKzTxxQ== + dependencies: + "@types/d3-selection" "*" + +"@types/d3-dsv@*": + version "3.0.7" + resolved "https://registry.npmmirror.com/@types/d3-dsv/-/d3-dsv-3.0.7.tgz#0a351f996dc99b37f4fa58b492c2d1c04e3dac17" + integrity sha512-n6QBF9/+XASqcKK6waudgL0pf/S5XHPPI8APyMLLUHd8NqouBGLsU8MgtO7NINGtPBtk9Kko/W4ea0oAspwh9g== + +"@types/d3-ease@*": + version "3.0.2" + resolved "https://registry.npmmirror.com/@types/d3-ease/-/d3-ease-3.0.2.tgz#e28db1bfbfa617076f7770dd1d9a48eaa3b6c51b" + integrity sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA== + +"@types/d3-fetch@*": + version "3.0.7" + resolved "https://registry.npmmirror.com/@types/d3-fetch/-/d3-fetch-3.0.7.tgz#c04a2b4f23181aa376f30af0283dbc7b3b569980" + integrity sha512-fTAfNmxSb9SOWNB9IoG5c8Hg6R+AzUHDRlsXsDZsNp6sxAEOP0tkP3gKkNSO/qmHPoBFTxNrjDprVHDQDvo5aA== + dependencies: + "@types/d3-dsv" "*" + +"@types/d3-force@*": + version "3.0.10" + resolved "https://registry.npmmirror.com/@types/d3-force/-/d3-force-3.0.10.tgz#6dc8fc6e1f35704f3b057090beeeb7ac674bff1a" + integrity sha512-ZYeSaCF3p73RdOKcjj+swRlZfnYpK1EbaDiYICEEp5Q6sUiqFaFQ9qgoshp5CzIyyb/yD09kD9o2zEltCexlgw== + +"@types/d3-format@*": + version "3.0.4" + resolved "https://registry.npmmirror.com/@types/d3-format/-/d3-format-3.0.4.tgz#b1e4465644ddb3fdf3a263febb240a6cd616de90" + integrity sha512-fALi2aI6shfg7vM5KiR1wNJnZ7r6UuggVqtDA+xiEdPZQwy/trcQaHnwShLuLdta2rTymCNpxYTiMZX/e09F4g== + +"@types/d3-geo@*": + version "3.1.0" + resolved "https://registry.npmmirror.com/@types/d3-geo/-/d3-geo-3.1.0.tgz#b9e56a079449174f0a2c8684a9a4df3f60522440" + integrity sha512-856sckF0oP/diXtS4jNsiQw/UuK5fQG8l/a9VVLeSouf1/PPbBE1i1W852zVwKwYCBkFJJB7nCFTbk6UMEXBOQ== + dependencies: + "@types/geojson" "*" + +"@types/d3-hierarchy@*": + version "3.1.7" + resolved "https://registry.npmmirror.com/@types/d3-hierarchy/-/d3-hierarchy-3.1.7.tgz#6023fb3b2d463229f2d680f9ac4b47466f71f17b" + integrity sha512-tJFtNoYBtRtkNysX1Xq4sxtjK8YgoWUNpIiUee0/jHGRwqvzYxkq0hGVbbOGSz+JgFxxRu4K8nb3YpG3CMARtg== + +"@types/d3-interpolate@*": + version "3.0.4" + resolved "https://registry.npmmirror.com/@types/d3-interpolate/-/d3-interpolate-3.0.4.tgz#412b90e84870285f2ff8a846c6eb60344f12a41c" + integrity sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA== + dependencies: + "@types/d3-color" "*" + +"@types/d3-path@*": + version "3.1.0" + resolved "https://registry.npmmirror.com/@types/d3-path/-/d3-path-3.1.0.tgz#2b907adce762a78e98828f0b438eaca339ae410a" + integrity sha512-P2dlU/q51fkOc/Gfl3Ul9kicV7l+ra934qBFXCFhrZMOL6du1TM0pm1ThYvENukyOn5h9v+yMJ9Fn5JK4QozrQ== + +"@types/d3-polygon@*": + version "3.0.2" + resolved "https://registry.npmmirror.com/@types/d3-polygon/-/d3-polygon-3.0.2.tgz#dfae54a6d35d19e76ac9565bcb32a8e54693189c" + integrity sha512-ZuWOtMaHCkN9xoeEMr1ubW2nGWsp4nIql+OPQRstu4ypeZ+zk3YKqQT0CXVe/PYqrKpZAi+J9mTs05TKwjXSRA== + +"@types/d3-quadtree@*": + version "3.0.6" + resolved "https://registry.npmmirror.com/@types/d3-quadtree/-/d3-quadtree-3.0.6.tgz#d4740b0fe35b1c58b66e1488f4e7ed02952f570f" + integrity sha512-oUzyO1/Zm6rsxKRHA1vH0NEDG58HrT5icx/azi9MF1TWdtttWl0UIUsjEQBBh+SIkrpd21ZjEv7ptxWys1ncsg== + +"@types/d3-random@*": + version "3.0.3" + resolved "https://registry.npmmirror.com/@types/d3-random/-/d3-random-3.0.3.tgz#ed995c71ecb15e0cd31e22d9d5d23942e3300cfb" + integrity sha512-Imagg1vJ3y76Y2ea0871wpabqp613+8/r0mCLEBfdtqC7xMSfj9idOnmBYyMoULfHePJyxMAw3nWhJxzc+LFwQ== + +"@types/d3-scale-chromatic@*": + version "3.1.0" + resolved "https://registry.npmmirror.com/@types/d3-scale-chromatic/-/d3-scale-chromatic-3.1.0.tgz#dc6d4f9a98376f18ea50bad6c39537f1b5463c39" + integrity sha512-iWMJgwkK7yTRmWqRB5plb1kadXyQ5Sj8V/zYlFGMUBbIPKQScw+Dku9cAAMgJG+z5GYDoMjWGLVOvjghDEFnKQ== + +"@types/d3-scale@*": + version "4.0.8" + resolved "https://registry.npmmirror.com/@types/d3-scale/-/d3-scale-4.0.8.tgz#d409b5f9dcf63074464bf8ddfb8ee5a1f95945bb" + integrity sha512-gkK1VVTr5iNiYJ7vWDI+yUFFlszhNMtVeneJ6lUTKPjprsvLLI9/tgEGiXJOnlINJA8FyA88gfnQsHbybVZrYQ== + dependencies: + "@types/d3-time" "*" + +"@types/d3-selection@*": + version "3.0.11" + resolved "https://registry.npmmirror.com/@types/d3-selection/-/d3-selection-3.0.11.tgz#bd7a45fc0a8c3167a631675e61bc2ca2b058d4a3" + integrity sha512-bhAXu23DJWsrI45xafYpkQ4NtcKMwWnAC/vKrd2l+nxMFuvOT3XMYTIj2opv8vq8AO5Yh7Qac/nSeP/3zjTK0w== + +"@types/d3-shape@*": + version "3.1.7" + resolved "https://registry.npmmirror.com/@types/d3-shape/-/d3-shape-3.1.7.tgz#2b7b423dc2dfe69c8c93596e673e37443348c555" + integrity sha512-VLvUQ33C+3J+8p+Daf+nYSOsjB4GXp19/S/aGo60m9h1v6XaxjiT82lKVWJCfzhtuZ3yD7i/TPeC/fuKLLOSmg== + dependencies: + "@types/d3-path" "*" + +"@types/d3-time-format@*": + version "4.0.3" + resolved "https://registry.npmmirror.com/@types/d3-time-format/-/d3-time-format-4.0.3.tgz#d6bc1e6b6a7db69cccfbbdd4c34b70632d9e9db2" + integrity sha512-5xg9rC+wWL8kdDj153qZcsJ0FWiFt0J5RB6LYUNZjwSnesfblqrI/bJ1wBdJ8OQfncgbJG5+2F+qfqnqyzYxyg== + +"@types/d3-time@*": + version "3.0.4" + resolved "https://registry.npmmirror.com/@types/d3-time/-/d3-time-3.0.4.tgz#8472feecd639691450dd8000eb33edd444e1323f" + integrity sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g== + +"@types/d3-timer@*": + version "3.0.2" + resolved "https://registry.npmmirror.com/@types/d3-timer/-/d3-timer-3.0.2.tgz#70bbda77dc23aa727413e22e214afa3f0e852f70" + integrity sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw== + +"@types/d3-transition@*": + version "3.0.9" + resolved "https://registry.npmmirror.com/@types/d3-transition/-/d3-transition-3.0.9.tgz#1136bc57e9ddb3c390dccc9b5ff3b7d2b8d94706" + integrity sha512-uZS5shfxzO3rGlu0cC3bjmMFKsXv+SmZZcgp0KD22ts4uGXp5EVYGzu/0YdwZeKmddhcAccYtREJKkPfXkZuCg== + dependencies: + "@types/d3-selection" "*" + +"@types/d3-zoom@*": + version "3.0.8" + resolved "https://registry.npmmirror.com/@types/d3-zoom/-/d3-zoom-3.0.8.tgz#dccb32d1c56b1e1c6e0f1180d994896f038bc40b" + integrity sha512-iqMC4/YlFCSlO8+2Ii1GGGliCAY4XdeG748w5vQUbevlbDu0zSjH/+jojorQVBK/se0j6DUFNPBGSqD3YWYnDw== + dependencies: + "@types/d3-interpolate" "*" + "@types/d3-selection" "*" + +"@types/d3@^7.4.3": + version "7.4.3" + resolved "https://registry.npmmirror.com/@types/d3/-/d3-7.4.3.tgz#d4550a85d08f4978faf0a4c36b848c61eaac07e2" + integrity sha512-lZXZ9ckh5R8uiFVt8ogUNf+pIrK4EsWrx2Np75WvF/eTpJ0FMHNhjXk8CKEx/+gpHbNQyJWehbFaTvqmHWB3ww== + dependencies: + "@types/d3-array" "*" + "@types/d3-axis" "*" + "@types/d3-brush" "*" + "@types/d3-chord" "*" + "@types/d3-color" "*" + "@types/d3-contour" "*" + "@types/d3-delaunay" "*" + "@types/d3-dispatch" "*" + "@types/d3-drag" "*" + "@types/d3-dsv" "*" + "@types/d3-ease" "*" + "@types/d3-fetch" "*" + "@types/d3-force" "*" + "@types/d3-format" "*" + "@types/d3-geo" "*" + "@types/d3-hierarchy" "*" + "@types/d3-interpolate" "*" + "@types/d3-path" "*" + "@types/d3-polygon" "*" + "@types/d3-quadtree" "*" + "@types/d3-random" "*" + "@types/d3-scale" "*" + "@types/d3-scale-chromatic" "*" + "@types/d3-selection" "*" + "@types/d3-shape" "*" + "@types/d3-time" "*" + "@types/d3-time-format" "*" + "@types/d3-timer" "*" + "@types/d3-transition" "*" + "@types/d3-zoom" "*" + "@types/eslint-scope@^3.7.3": version "3.7.7" resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.7.tgz#3108bd5f18b0cdb277c867b3dd449c9ed7079ac5" @@ -2412,6 +2698,11 @@ "@types/qs" "*" "@types/serve-static" "*" +"@types/geojson@*": + version "7946.0.15" + resolved "https://registry.npmmirror.com/@types/geojson/-/geojson-7946.0.15.tgz#f9d55fd5a0aa2de9dc80b1b04e437538b7298868" + integrity sha512-9oSxFzDCT2Rj6DfcHF8G++jxBKS7mBqXl5xrRW+Kbvjry6Uduya2iiwqHPhVXpasAVMBYKkEPGgKhd3+/HZ6xA== + "@types/glob@^7.1.1": version "7.2.0" resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.2.0.tgz#bc1b5bf3aa92f25bd5dd39f35c57361bdce5b2eb" @@ -2576,6 +2867,11 @@ resolved "https://registry.yarnpkg.com/@types/swagger-schema-official/-/swagger-schema-official-2.0.25.tgz#c8073914004d0a9c5412aeaf458d96e34c504840" integrity sha512-T92Xav+Gf/Ik1uPW581nA+JftmjWPgskw/WBf4TJzxRG/SJ+DfNnNE+WuZ4mrXuzflQMqMkm1LSYjzYW7MB1Cg== +"@types/trusted-types@^2.0.7": + version "2.0.7" + resolved "https://registry.npmmirror.com/@types/trusted-types/-/trusted-types-2.0.7.tgz#baccb07a970b91707df3a3e8ba6896c57ead2d11" + integrity sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw== + "@types/unist@*", "@types/unist@^3.0.0": version "3.0.2" resolved "https://registry.yarnpkg.com/@types/unist/-/unist-3.0.2.tgz#6dd61e43ef60b34086287f83683a5c1b2dc53d20" @@ -2991,6 +3287,11 @@ acorn@^8.11.0, acorn@^8.4.1, acorn@^8.7.1, acorn@^8.8.2, acorn@^8.9.0: resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.12.1.tgz#71616bdccbe25e27a54439e0046e89ca76df2248" integrity sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg== +acorn@^8.14.0: + version "8.14.0" + resolved "https://registry.npmmirror.com/acorn/-/acorn-8.14.0.tgz#063e2c70cac5fb4f6467f0b11152e04c682795b0" + integrity sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA== + adjust-sourcemap-loader@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/adjust-sourcemap-loader/-/adjust-sourcemap-loader-4.0.0.tgz#fc4a0fd080f7d10471f30a7320f25560ade28c99" @@ -3813,6 +4114,25 @@ chardet@^0.7.0: resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== +chevrotain-allstar@~0.3.0: + version "0.3.1" + resolved "https://registry.npmmirror.com/chevrotain-allstar/-/chevrotain-allstar-0.3.1.tgz#b7412755f5d83cc139ab65810cdb00d8db40e6ca" + integrity sha512-b7g+y9A0v4mxCW1qUhf3BSVPg+/NvGErk/dOkrDaHA0nQIQGAtrOjlX//9OQtRlSCy+x9rfB5N8yC71lH1nvMw== + dependencies: + lodash-es "^4.17.21" + +chevrotain@~11.0.3: + version "11.0.3" + resolved "https://registry.npmmirror.com/chevrotain/-/chevrotain-11.0.3.tgz#88ffc1fb4b5739c715807eaeedbbf200e202fc1b" + integrity sha512-ci2iJH6LeIkvP9eJW6gpueU8cnZhv85ELY8w8WiFtNjMHA5ad6pQLaJo9mEly/9qUyCpvqX8/POVUTf18/HFdw== + dependencies: + "@chevrotain/cst-dts-gen" "11.0.3" + "@chevrotain/gast" "11.0.3" + "@chevrotain/regexp-to-ast" "11.0.3" + "@chevrotain/types" "11.0.3" + "@chevrotain/utils" "11.0.3" + lodash-es "4.17.21" + "chokidar@>=3.0.0 <4.0.0", chokidar@^3.0.0, chokidar@^3.5.1, chokidar@^3.5.3: version "3.6.0" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b" @@ -3897,6 +4217,15 @@ cli-width@^4.1.0: resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-4.1.0.tgz#42daac41d3c254ef38ad8ac037672130173691c5" integrity sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ== +clipboard@^2.0.11: + version "2.0.11" + resolved "https://registry.npmmirror.com/clipboard/-/clipboard-2.0.11.tgz#62180360b97dd668b6b3a84ec226975762a70be5" + integrity sha512-C+0bbOqkezLIsmWSvlsXS0Q0bmkugu7jcfMIACB+RDEntIzQIkdr148we28AfSloQLRdZlYL/QYyrq05j/3Faw== + dependencies: + good-listener "^1.2.2" + select "^1.1.2" + tiny-emitter "^2.0.0" + cliui@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/cliui/-/cliui-6.0.0.tgz#511d702c0c4e41ca156d7d0e96021f23e13225b1" @@ -4020,11 +4349,21 @@ commander@11.0.0: resolved "https://registry.yarnpkg.com/commander/-/commander-11.0.0.tgz#43e19c25dbedc8256203538e8d7e9346877a6f67" integrity sha512-9HMlXtt/BNoYr8ooyjjNRdIilOTkVJXB+GhxMTtOKwk0R4j4lS4NpjuqmRxroBfnfTSHQIHQB7wryHhXarNjmQ== +commander@7: + version "7.2.0" + resolved "https://registry.npmmirror.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7" + integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw== + commander@^2.20.0: version "2.20.3" resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== +commander@^8.3.0: + version "8.3.0" + resolved "https://registry.npmmirror.com/commander/-/commander-8.3.0.tgz#4837ea1b2da67b9c616a67afbb0fafee567bca66" + integrity sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww== + comment-parser@1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/comment-parser/-/comment-parser-1.4.1.tgz#bdafead37961ac079be11eb7ec65c4d021eaf9cc" @@ -4065,6 +4404,11 @@ concat-map@0.0.1: resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== +confbox@^0.1.8: + version "0.1.8" + resolved "https://registry.npmmirror.com/confbox/-/confbox-0.1.8.tgz#820d73d3b3c82d9bd910652c5d4d599ef8ff8b06" + integrity sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w== + connect-history-api-fallback@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz#647264845251a0daf25b97ce87834cace0f5f1c8" @@ -4171,6 +4515,20 @@ cors@~2.8.5: object-assign "^4" vary "^1" +cose-base@^1.0.0: + version "1.0.3" + resolved "https://registry.npmmirror.com/cose-base/-/cose-base-1.0.3.tgz#650334b41b869578a543358b80cda7e0abe0a60a" + integrity sha512-s9whTXInMSgAp/NVXVNuVxVKzGH2qck3aQlVHxDCdAEPgtMKwc4Wq6/QKhgdEdgbLSi9rBTAcPoRa6JpiG4ksg== + dependencies: + layout-base "^1.0.0" + +cose-base@^2.2.0: + version "2.2.0" + resolved "https://registry.npmmirror.com/cose-base/-/cose-base-2.2.0.tgz#1c395c35b6e10bb83f9769ca8b817d614add5c01" + integrity sha512-AzlgcsCbUMymkADOJtQm3wO9S3ltPfYOFD5033keQn9NJzIbtnZj+UdBJe7DYml/8TdbtHJW3j58SOnKhWY/5g== + dependencies: + layout-base "^2.0.0" + cosmiconfig@7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-7.0.1.tgz#714d756522cace867867ccb4474c5d01bbae5d6d" @@ -4302,6 +4660,304 @@ custom-event@~1.0.0: resolved "https://registry.yarnpkg.com/custom-event/-/custom-event-1.0.1.tgz#5d02a46850adf1b4a317946a3928fccb5bfd0425" integrity sha512-GAj5FOq0Hd+RsCGVJxZuKaIDXDf3h6GQoNEjFgbLLI/trgtavwUbSnZ5pVfg27DVCaWjIohryS0JFwIJyT2cMg== +cytoscape-cose-bilkent@^4.1.0: + version "4.1.0" + resolved "https://registry.npmmirror.com/cytoscape-cose-bilkent/-/cytoscape-cose-bilkent-4.1.0.tgz#762fa121df9930ffeb51a495d87917c570ac209b" + integrity sha512-wgQlVIUJF13Quxiv5e1gstZ08rnZj2XaLHGoFMYXz7SkNfCDOOteKBE6SYRfA9WxxI/iBc3ajfDoc6hb/MRAHQ== + dependencies: + cose-base "^1.0.0" + +cytoscape-fcose@^2.2.0: + version "2.2.0" + resolved "https://registry.npmmirror.com/cytoscape-fcose/-/cytoscape-fcose-2.2.0.tgz#e4d6f6490df4fab58ae9cea9e5c3ab8d7472f471" + integrity sha512-ki1/VuRIHFCzxWNrsshHYPs6L7TvLu3DL+TyIGEsRcvVERmxokbf5Gdk7mFxZnTdiGtnA4cfSmjZJMviqSuZrQ== + dependencies: + cose-base "^2.2.0" + +cytoscape@^3.29.2: + version "3.30.4" + resolved "https://registry.npmmirror.com/cytoscape/-/cytoscape-3.30.4.tgz#3404da0a159c00a1a3df2c85b2b43fdc66a0e28e" + integrity sha512-OxtlZwQl1WbwMmLiyPSEBuzeTIQnwZhJYYWFzZ2PhEHVFwpeaqNIkUzSiso00D98qk60l8Gwon2RP304d3BJ1A== + +"d3-array@1 - 2": + version "2.12.1" + resolved "https://registry.npmmirror.com/d3-array/-/d3-array-2.12.1.tgz#e20b41aafcdffdf5d50928004ececf815a465e81" + integrity sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ== + dependencies: + internmap "^1.0.0" + +"d3-array@2 - 3", "d3-array@2.10.0 - 3", "d3-array@2.5.0 - 3", d3-array@3, d3-array@^3.2.0: + version "3.2.4" + resolved "https://registry.npmmirror.com/d3-array/-/d3-array-3.2.4.tgz#15fec33b237f97ac5d7c986dc77da273a8ed0bb5" + integrity sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg== + dependencies: + internmap "1 - 2" + +d3-axis@3: + version "3.0.0" + resolved "https://registry.npmmirror.com/d3-axis/-/d3-axis-3.0.0.tgz#c42a4a13e8131d637b745fc2973824cfeaf93322" + integrity sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw== + +d3-brush@3: + version "3.0.0" + resolved "https://registry.npmmirror.com/d3-brush/-/d3-brush-3.0.0.tgz#6f767c4ed8dcb79de7ede3e1c0f89e63ef64d31c" + integrity sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ== + dependencies: + d3-dispatch "1 - 3" + d3-drag "2 - 3" + d3-interpolate "1 - 3" + d3-selection "3" + d3-transition "3" + +d3-chord@3: + version "3.0.1" + resolved "https://registry.npmmirror.com/d3-chord/-/d3-chord-3.0.1.tgz#d156d61f485fce8327e6abf339cb41d8cbba6966" + integrity sha512-VE5S6TNa+j8msksl7HwjxMHDM2yNK3XCkusIlpX5kwauBfXuyLAtNg9jCp/iHH61tgI4sb6R/EIMWCqEIdjT/g== + dependencies: + d3-path "1 - 3" + +"d3-color@1 - 3", d3-color@3: + version "3.1.0" + resolved "https://registry.npmmirror.com/d3-color/-/d3-color-3.1.0.tgz#395b2833dfac71507f12ac2f7af23bf819de24e2" + integrity sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA== + +d3-contour@4: + version "4.0.2" + resolved "https://registry.npmmirror.com/d3-contour/-/d3-contour-4.0.2.tgz#bb92063bc8c5663acb2422f99c73cbb6c6ae3bcc" + integrity sha512-4EzFTRIikzs47RGmdxbeUvLWtGedDUNkTcmzoeyg4sP/dvCexO47AaQL7VKy/gul85TOxw+IBgA8US2xwbToNA== + dependencies: + d3-array "^3.2.0" + +d3-delaunay@6: + version "6.0.4" + resolved "https://registry.npmmirror.com/d3-delaunay/-/d3-delaunay-6.0.4.tgz#98169038733a0a5babbeda55054f795bb9e4a58b" + integrity sha512-mdjtIZ1XLAM8bm/hx3WwjfHt6Sggek7qH043O8KEjDXN40xi3vx/6pYSVTwLjEgiXQTbvaouWKynLBiUZ6SK6A== + dependencies: + delaunator "5" + +"d3-dispatch@1 - 3", d3-dispatch@3: + version "3.0.1" + resolved "https://registry.npmmirror.com/d3-dispatch/-/d3-dispatch-3.0.1.tgz#5fc75284e9c2375c36c839411a0cf550cbfc4d5e" + integrity sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg== + +"d3-drag@2 - 3", d3-drag@3: + version "3.0.0" + resolved "https://registry.npmmirror.com/d3-drag/-/d3-drag-3.0.0.tgz#994aae9cd23c719f53b5e10e3a0a6108c69607ba" + integrity sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg== + dependencies: + d3-dispatch "1 - 3" + d3-selection "3" + +"d3-dsv@1 - 3", d3-dsv@3: + version "3.0.1" + resolved "https://registry.npmmirror.com/d3-dsv/-/d3-dsv-3.0.1.tgz#c63af978f4d6a0d084a52a673922be2160789b73" + integrity sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q== + dependencies: + commander "7" + iconv-lite "0.6" + rw "1" + +"d3-ease@1 - 3", d3-ease@3: + version "3.0.1" + resolved "https://registry.npmmirror.com/d3-ease/-/d3-ease-3.0.1.tgz#9658ac38a2140d59d346160f1f6c30fda0bd12f4" + integrity sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w== + +d3-fetch@3: + version "3.0.1" + resolved "https://registry.npmmirror.com/d3-fetch/-/d3-fetch-3.0.1.tgz#83141bff9856a0edb5e38de89cdcfe63d0a60a22" + integrity sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw== + dependencies: + d3-dsv "1 - 3" + +d3-force@3: + version "3.0.0" + resolved "https://registry.npmmirror.com/d3-force/-/d3-force-3.0.0.tgz#3e2ba1a61e70888fe3d9194e30d6d14eece155c4" + integrity sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg== + dependencies: + d3-dispatch "1 - 3" + d3-quadtree "1 - 3" + d3-timer "1 - 3" + +"d3-format@1 - 3", d3-format@3: + version "3.1.0" + resolved "https://registry.npmmirror.com/d3-format/-/d3-format-3.1.0.tgz#9260e23a28ea5cb109e93b21a06e24e2ebd55641" + integrity sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA== + +d3-geo@3: + version "3.1.1" + resolved "https://registry.npmmirror.com/d3-geo/-/d3-geo-3.1.1.tgz#6027cf51246f9b2ebd64f99e01dc7c3364033a4d" + integrity sha512-637ln3gXKXOwhalDzinUgY83KzNWZRKbYubaG+fGVuc/dxO64RRljtCTnf5ecMyE1RIdtqpkVcq0IbtU2S8j2Q== + dependencies: + d3-array "2.5.0 - 3" + +d3-hierarchy@3: + version "3.1.2" + resolved "https://registry.npmmirror.com/d3-hierarchy/-/d3-hierarchy-3.1.2.tgz#b01cd42c1eed3d46db77a5966cf726f8c09160c6" + integrity sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA== + +"d3-interpolate@1 - 3", "d3-interpolate@1.2.0 - 3", d3-interpolate@3: + version "3.0.1" + resolved "https://registry.npmmirror.com/d3-interpolate/-/d3-interpolate-3.0.1.tgz#3c47aa5b32c5b3dfb56ef3fd4342078a632b400d" + integrity sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g== + dependencies: + d3-color "1 - 3" + +d3-path@1: + version "1.0.9" + resolved "https://registry.npmmirror.com/d3-path/-/d3-path-1.0.9.tgz#48c050bb1fe8c262493a8caf5524e3e9591701cf" + integrity sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg== + +"d3-path@1 - 3", d3-path@3, d3-path@^3.1.0: + version "3.1.0" + resolved "https://registry.npmmirror.com/d3-path/-/d3-path-3.1.0.tgz#22df939032fb5a71ae8b1800d61ddb7851c42526" + integrity sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ== + +d3-polygon@3: + version "3.0.1" + resolved "https://registry.npmmirror.com/d3-polygon/-/d3-polygon-3.0.1.tgz#0b45d3dd1c48a29c8e057e6135693ec80bf16398" + integrity sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg== + +"d3-quadtree@1 - 3", d3-quadtree@3: + version "3.0.1" + resolved "https://registry.npmmirror.com/d3-quadtree/-/d3-quadtree-3.0.1.tgz#6dca3e8be2b393c9a9d514dabbd80a92deef1a4f" + integrity sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw== + +d3-random@3: + version "3.0.1" + resolved "https://registry.npmmirror.com/d3-random/-/d3-random-3.0.1.tgz#d4926378d333d9c0bfd1e6fa0194d30aebaa20f4" + integrity sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ== + +d3-sankey@^0.12.3: + version "0.12.3" + resolved "https://registry.npmmirror.com/d3-sankey/-/d3-sankey-0.12.3.tgz#b3c268627bd72e5d80336e8de6acbfec9d15d01d" + integrity sha512-nQhsBRmM19Ax5xEIPLMY9ZmJ/cDvd1BG3UVvt5h3WRxKg5zGRbvnteTyWAbzeSvlh3tW7ZEmq4VwR5mB3tutmQ== + dependencies: + d3-array "1 - 2" + d3-shape "^1.2.0" + +d3-scale-chromatic@3: + version "3.1.0" + resolved "https://registry.npmmirror.com/d3-scale-chromatic/-/d3-scale-chromatic-3.1.0.tgz#34c39da298b23c20e02f1a4b239bd0f22e7f1314" + integrity sha512-A3s5PWiZ9YCXFye1o246KoscMWqf8BsD9eRiJ3He7C9OBaxKhAd5TFCdEx/7VbKtxxTsu//1mMJFrEt572cEyQ== + dependencies: + d3-color "1 - 3" + d3-interpolate "1 - 3" + +d3-scale@4: + version "4.0.2" + resolved "https://registry.npmmirror.com/d3-scale/-/d3-scale-4.0.2.tgz#82b38e8e8ff7080764f8dcec77bd4be393689396" + integrity sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ== + dependencies: + d3-array "2.10.0 - 3" + d3-format "1 - 3" + d3-interpolate "1.2.0 - 3" + d3-time "2.1.1 - 3" + d3-time-format "2 - 4" + +"d3-selection@2 - 3", d3-selection@3: + version "3.0.0" + resolved "https://registry.npmmirror.com/d3-selection/-/d3-selection-3.0.0.tgz#c25338207efa72cc5b9bd1458a1a41901f1e1b31" + integrity sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ== + +d3-shape@3: + version "3.2.0" + resolved "https://registry.npmmirror.com/d3-shape/-/d3-shape-3.2.0.tgz#a1a839cbd9ba45f28674c69d7f855bcf91dfc6a5" + integrity sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA== + dependencies: + d3-path "^3.1.0" + +d3-shape@^1.2.0: + version "1.3.7" + resolved "https://registry.npmmirror.com/d3-shape/-/d3-shape-1.3.7.tgz#df63801be07bc986bc54f63789b4fe502992b5d7" + integrity sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw== + dependencies: + d3-path "1" + +"d3-time-format@2 - 4", d3-time-format@4: + version "4.1.0" + resolved "https://registry.npmmirror.com/d3-time-format/-/d3-time-format-4.1.0.tgz#7ab5257a5041d11ecb4fe70a5c7d16a195bb408a" + integrity sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg== + dependencies: + d3-time "1 - 3" + +"d3-time@1 - 3", "d3-time@2.1.1 - 3", d3-time@3: + version "3.1.0" + resolved "https://registry.npmmirror.com/d3-time/-/d3-time-3.1.0.tgz#9310db56e992e3c0175e1ef385e545e48a9bb5c7" + integrity sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q== + dependencies: + d3-array "2 - 3" + +"d3-timer@1 - 3", d3-timer@3: + version "3.0.1" + resolved "https://registry.npmmirror.com/d3-timer/-/d3-timer-3.0.1.tgz#6284d2a2708285b1abb7e201eda4380af35e63b0" + integrity sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA== + +"d3-transition@2 - 3", d3-transition@3: + version "3.0.1" + resolved "https://registry.npmmirror.com/d3-transition/-/d3-transition-3.0.1.tgz#6869fdde1448868077fdd5989200cb61b2a1645f" + integrity sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w== + dependencies: + d3-color "1 - 3" + d3-dispatch "1 - 3" + d3-ease "1 - 3" + d3-interpolate "1 - 3" + d3-timer "1 - 3" + +d3-zoom@3: + version "3.0.0" + resolved "https://registry.npmmirror.com/d3-zoom/-/d3-zoom-3.0.0.tgz#d13f4165c73217ffeaa54295cd6969b3e7aee8f3" + integrity sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw== + dependencies: + d3-dispatch "1 - 3" + d3-drag "2 - 3" + d3-interpolate "1 - 3" + d3-selection "2 - 3" + d3-transition "2 - 3" + +d3@^7.9.0: + version "7.9.0" + resolved "https://registry.npmmirror.com/d3/-/d3-7.9.0.tgz#579e7acb3d749caf8860bd1741ae8d371070cd5d" + integrity sha512-e1U46jVP+w7Iut8Jt8ri1YsPOvFpg46k+K8TpCb0P+zjCkjkPnV7WzfDJzMHy1LnA+wj5pLT1wjO901gLXeEhA== + dependencies: + d3-array "3" + d3-axis "3" + d3-brush "3" + d3-chord "3" + d3-color "3" + d3-contour "4" + d3-delaunay "6" + d3-dispatch "3" + d3-drag "3" + d3-dsv "3" + d3-ease "3" + d3-fetch "3" + d3-force "3" + d3-format "3" + d3-geo "3" + d3-hierarchy "3" + d3-interpolate "3" + d3-path "3" + d3-polygon "3" + d3-quadtree "3" + d3-random "3" + d3-scale "4" + d3-scale-chromatic "3" + d3-selection "3" + d3-shape "3" + d3-time "3" + d3-time-format "4" + d3-timer "3" + d3-transition "3" + d3-zoom "3" + +dagre-d3-es@7.0.11: + version "7.0.11" + resolved "https://registry.npmmirror.com/dagre-d3-es/-/dagre-d3-es-7.0.11.tgz#2237e726c0577bfe67d1a7cfd2265b9ab2c15c40" + integrity sha512-tvlJLyQf834SylNKax8Wkzco/1ias1OPw8DcUMDE7oUIoSEW25riQVuiu/0OWEFqT0cxHT3Pa9/D82Jr47IONw== + dependencies: + d3 "^7.9.0" + lodash-es "^4.17.21" + dashdash@^1.12.0: version "1.14.1" resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" @@ -4353,6 +5009,11 @@ date-format@^4.0.14: resolved "https://registry.yarnpkg.com/date-format/-/date-format-4.0.14.tgz#7a8e584434fb169a521c8b7aa481f355810d9400" integrity sha512-39BOQLs9ZjKh0/patS9nrT8wc3ioX3/eA/zgbKNopnF2wCqJEoxywwwElATYvRsXdnOxA/OQeQoFZ3rFjVajhg== +dayjs@^1.11.10: + version "1.11.13" + resolved "https://registry.npmmirror.com/dayjs/-/dayjs-1.11.13.tgz#92430b0139055c3ebb60150aa13e860a4b5a366c" + integrity sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg== + debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.9: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" @@ -4381,6 +5042,13 @@ debug@^3.1.0, debug@^3.2.7: dependencies: ms "^2.1.1" +debug@^4.4.0: + version "4.4.0" + resolved "https://registry.npmmirror.com/debug/-/debug-4.4.0.tgz#2b3f2aea2ffeb776477460267377dc8710faba8a" + integrity sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA== + dependencies: + ms "^2.1.3" + decamelize-keys@^1.0.0, decamelize-keys@^1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/decamelize-keys/-/decamelize-keys-1.1.1.tgz#04a2d523b2f18d80d0158a43b895d56dff8d19d8" @@ -4476,11 +5144,23 @@ del@^2.2.0: pinkie-promise "^2.0.0" rimraf "^2.2.8" +delaunator@5: + version "5.0.1" + resolved "https://registry.npmmirror.com/delaunator/-/delaunator-5.0.1.tgz#39032b08053923e924d6094fe2cde1a99cc51278" + integrity sha512-8nvh+XBe96aCESrGOqMp/84b13H9cdKbG5P2ejQCh4d4sK9RL4371qou9drQjMhvnPmhWl5hnmqbEE0fXr9Xnw== + dependencies: + robust-predicates "^3.0.2" + delayed-stream@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== +delegate@^3.1.2: + version "3.2.0" + resolved "https://registry.npmmirror.com/delegate/-/delegate-3.2.0.tgz#b66b71c3158522e8ab5744f720d8ca0c2af59166" + integrity sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw== + depd@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" @@ -4612,6 +5292,13 @@ domhandler@^5.0.2, domhandler@^5.0.3: dependencies: domelementtype "^2.3.0" +dompurify@^3.2.1: + version "3.2.3" + resolved "https://registry.npmmirror.com/dompurify/-/dompurify-3.2.3.tgz#05dd2175225324daabfca6603055a09b2382a4cd" + integrity sha512-U1U5Hzc2MO0oW3DF+G9qYN0aT7atAou4AgI0XjWz061nyBPbdxkfdhfy5uMgGn6+oLFCfn44ZGbdDqCzVmlOWA== + optionalDependencies: + "@types/trusted-types" "^2.0.7" + domutils@^1.5.1: version "1.7.0" resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.7.0.tgz#56ea341e834e06e6748af7a1cb25da67ea9f8c2a" @@ -4706,6 +5393,11 @@ emoji-regex@^9.2.2: resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== +"emoji-toolkit@>= 8.0.0 < 10.0.0": + version "9.0.1" + resolved "https://registry.npmmirror.com/emoji-toolkit/-/emoji-toolkit-9.0.1.tgz#b3da51a4d9b1e89608b6a8506a5df6dbc3125495" + integrity sha512-sMMNqKNLVHXJfIKoPbrRJwtYuysVNC9GlKetr72zE3SSVbHqoeDLWVrxP0uM0AE0qvdl3hbUk+tJhhwXZrDHaw== + emojis-list@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78" @@ -5910,6 +6602,11 @@ globals@^13.19.0: dependencies: type-fest "^0.20.2" +globals@^15.13.0: + version "15.14.0" + resolved "https://registry.npmmirror.com/globals/-/globals-15.14.0.tgz#b8fd3a8941ff3b4d38f3319d433b61bbb482e73f" + integrity sha512-OkToC372DtlQeje9/zHIo5CT8lRP/FUgEOKBEhU4e0abL7J7CD24fD9ohiLN5hagG/kWCYj4K5oaxxtj2Z0Dig== + globalthis@^1.0.3: version "1.0.4" resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.4.tgz#7430ed3a975d97bfb59bcce41f5cabbafa651236" @@ -5979,6 +6676,13 @@ gonzales-pe@^4.2.3: dependencies: minimist "^1.2.5" +good-listener@^1.2.2: + version "1.2.2" + resolved "https://registry.npmmirror.com/good-listener/-/good-listener-1.2.2.tgz#d53b30cdf9313dffb7dc9a0d477096aa6d145c50" + integrity sha512-goW1b+d9q/HIwbVYZzZ6SsTr4IgE+WA44A0GmPIQstuOrgsFcT7VEJ48nmr9GaRtNu0XTKacFLGnBPAM6Afouw== + dependencies: + delegate "^3.1.2" + gopd@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c" @@ -6003,6 +6707,11 @@ gzip-size@^6.0.0: dependencies: duplexer "^0.1.2" +hachure-fill@^0.5.2: + version "0.5.2" + resolved "https://registry.npmmirror.com/hachure-fill/-/hachure-fill-0.5.2.tgz#d19bc4cc8750a5962b47fb1300557a85fcf934cc" + integrity sha512-3GKBOn+m2LX9iq+JC1064cSFprJY4jL1jCXTcpnfER5HYE2l/4EfWSGzkPa/ZDBmYI0ZOEj5VHV/eKnPGkHuOg== + handle-thing@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/handle-thing/-/handle-thing-2.0.1.tgz#857f79ce359580c340d43081cc648970d0bb234e" @@ -6310,7 +7019,7 @@ iconv-lite@0.4.24, iconv-lite@^0.4.24: dependencies: safer-buffer ">= 2.1.2 < 3" -iconv-lite@^0.6.2, iconv-lite@^0.6.3: +iconv-lite@0.6, iconv-lite@^0.6.2, iconv-lite@^0.6.3: version "0.6.3" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501" integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw== @@ -6468,6 +7177,16 @@ internal-slot@^1.0.7: hasown "^2.0.0" side-channel "^1.0.4" +"internmap@1 - 2": + version "2.0.3" + resolved "https://registry.npmmirror.com/internmap/-/internmap-2.0.3.tgz#6685f23755e43c524e251d29cbc97248e3061009" + integrity sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg== + +internmap@^1.0.0: + version "1.0.1" + resolved "https://registry.npmmirror.com/internmap/-/internmap-1.0.1.tgz#0017cc8a3b99605f0302f2b198d272e015e5df95" + integrity sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw== + ip-address@^9.0.5: version "9.0.5" resolved "https://registry.yarnpkg.com/ip-address/-/ip-address-9.0.5.tgz#117a960819b08780c3bd1f14ef3c1cc1d3f3ea5a" @@ -7267,6 +7986,13 @@ karma@6.4.2: ua-parser-js "^0.7.30" yargs "^16.1.1" +katex@^0.16.0, katex@^0.16.9: + version "0.16.19" + resolved "https://registry.npmmirror.com/katex/-/katex-0.16.19.tgz#698e026188876f9c8c93d3ecb27b212aaa056d0a" + integrity sha512-3IA6DYVhxhBabjSLTNO9S4+OliA3Qvb8pBQXMfC4WxXJgLwZgnfDl0BmB4z6nBMdznBsZ+CGM8DrGZ5hcguDZg== + dependencies: + commander "^8.3.0" + keyv@^4.5.3: version "4.5.4" resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93" @@ -7274,6 +8000,11 @@ keyv@^4.5.3: dependencies: json-buffer "3.0.1" +khroma@^2.1.0: + version "2.1.0" + resolved "https://registry.npmmirror.com/khroma/-/khroma-2.1.0.tgz#45f2ce94ce231a437cf5b63c2e886e6eb42bbbb1" + integrity sha512-Ls993zuzfayK269Svk9hzpeGUKob/sIgZzyHYdjQoAdQetRKpOLj+k/QQQ/6Qi0Yz65mlROrfd+Ev+1+7dz9Kw== + kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: version "3.2.2" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" @@ -7308,6 +8039,22 @@ known-css-properties@^0.26.0: resolved "https://registry.yarnpkg.com/known-css-properties/-/known-css-properties-0.26.0.tgz#008295115abddc045a9f4ed7e2a84dc8b3a77649" integrity sha512-5FZRzrZzNTBruuurWpvZnvP9pum+fe0HcK8z/ooo+U+Hmp4vtbyp1/QDsqmufirXy4egGzbaH/y2uCZf+6W5Kg== +kolorist@^1.8.0: + version "1.8.0" + resolved "https://registry.npmmirror.com/kolorist/-/kolorist-1.8.0.tgz#edddbbbc7894bc13302cdf740af6374d4a04743c" + integrity sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ== + +langium@3.0.0: + version "3.0.0" + resolved "https://registry.npmmirror.com/langium/-/langium-3.0.0.tgz#4938294eb57c59066ef955070ac4d0c917b26026" + integrity sha512-+Ez9EoiByeoTu/2BXmEaZ06iPNXM6thWJp02KfBO/raSMyCJ4jw7AkWWa+zBCTm0+Tw1Fj9FOxdqSskyN5nAwg== + dependencies: + chevrotain "~11.0.3" + chevrotain-allstar "~0.3.0" + vscode-languageserver "~9.0.1" + vscode-languageserver-textdocument "~1.0.11" + vscode-uri "~3.0.8" + launch-editor@^2.6.0: version "2.8.0" resolved "https://registry.yarnpkg.com/launch-editor/-/launch-editor-2.8.0.tgz#7255d90bdba414448e2138faa770a74f28451305" @@ -7316,6 +8063,16 @@ launch-editor@^2.6.0: picocolors "^1.0.0" shell-quote "^1.8.1" +layout-base@^1.0.0: + version "1.0.2" + resolved "https://registry.npmmirror.com/layout-base/-/layout-base-1.0.2.tgz#1291e296883c322a9dd4c5dd82063721b53e26e2" + integrity sha512-8h2oVEZNktL4BH2JCOI90iD1yXwL6iNW7KcCKT2QZgQJR2vbqDsldCTPRU9NifTCqHZci57XvQQ15YTu+sTYPg== + +layout-base@^2.0.0: + version "2.0.1" + resolved "https://registry.npmmirror.com/layout-base/-/layout-base-2.0.1.tgz#d0337913586c90f9c2c075292069f5c2da5dd285" + integrity sha512-dp3s92+uNI1hWIpPGH3jK2kxE2lMjdXdr+DH8ynZHpd6PUlH6x6cbuXnoMmiNumznqaNO31xu9e79F0uuZ0JFg== + less-loader@11.1.0: version "11.1.0" resolved "https://registry.yarnpkg.com/less-loader/-/less-loader-11.1.0.tgz#a452384259bdf8e4f6d5fdcc39543609e6313f82" @@ -7458,6 +8215,14 @@ loadjs@^4.2.0: resolved "https://registry.yarnpkg.com/loadjs/-/loadjs-4.3.0.tgz#38c578cbb2e08835aa4407bd4ac6507dd1f7ed10" integrity sha512-vNX4ZZLJBeDEOBvdr2v/F+0aN5oMuPu7JTqrMwp+DtgK+AryOlpy6Xtm2/HpNr+azEa828oQjOtWsB6iDtSfSQ== +local-pkg@^0.5.1: + version "0.5.1" + resolved "https://registry.npmmirror.com/local-pkg/-/local-pkg-0.5.1.tgz#69658638d2a95287534d4c2fff757980100dbb6d" + integrity sha512-9rrA30MRRP3gBD3HTGnC6cDFpaE1kVDWxWgqWJUN0RvDNAo+Nz/9GxB+nHOH0ifbVFy0hSA1V6vFDvnx54lTEQ== + dependencies: + mlly "^1.7.3" + pkg-types "^1.2.1" + locate-path@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" @@ -7487,6 +8252,11 @@ locate-path@^7.1.0: dependencies: p-locate "^6.0.0" +lodash-es@4.17.21, lodash-es@^4.17.21: + version "4.17.21" + resolved "https://registry.npmmirror.com/lodash-es/-/lodash-es-4.17.21.tgz#43e626c46e6591b7750beb2b50117390c609e3ee" + integrity sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw== + lodash.debounce@^4.0.8: version "4.0.8" resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" @@ -7665,6 +8435,16 @@ markdown-table@^1.1.0: resolved "https://registry.yarnpkg.com/markdown-table/-/markdown-table-1.1.3.tgz#9fcb69bcfdb8717bfd0398c6ec2d93036ef8de60" integrity sha512-1RUZVgQlpJSPWYbFSpmudq5nHY1doEIv89gBtF0s4gW1GF2XorxcA/70M5vq7rLv0a6mhOUccRsqkwhwLCIQ2Q== +marked@15.0.6: + version "15.0.6" + resolved "https://registry.npmmirror.com/marked/-/marked-15.0.6.tgz#8165f16afb6f4b30a35bdcee657c3b8415820a8f" + integrity sha512-Y07CUOE+HQXbVDCGl3LXggqJDbXDP2pArc2C1N1RRMN0ONiShoSsIInMd5Gsxupe7fKLpgimTV+HOJ9r7bA+pg== + +marked@^13.0.2: + version "13.0.3" + resolved "https://registry.npmmirror.com/marked/-/marked-13.0.3.tgz#5c5b4a5d0198060c7c9bc6ef9420a7fed30f822d" + integrity sha512-rqRix3/TWzE9rIoFGIn8JmsVfhiuC8VIQ8IdX5TfzmeBucdY05/0UlzKaw0eVtpcN/OdVFpBk7CjKGo9iHJ/zA== + mathml-tag-names@^2.0.1, mathml-tag-names@^2.1.3: version "2.1.3" resolved "https://registry.yarnpkg.com/mathml-tag-names/-/mathml-tag-names-2.1.3.tgz#4ddadd67308e780cf16a47685878ee27b736a0a3" @@ -7737,6 +8517,32 @@ merge2@^1.2.3, merge2@^1.3.0, merge2@^1.4.1: resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== +"mermaid@>= 10.6.0 < 12.0.0": + version "11.4.1" + resolved "https://registry.npmmirror.com/mermaid/-/mermaid-11.4.1.tgz#577fad5c31a01a06d9f793e298d411f1379eecc8" + integrity sha512-Mb01JT/x6CKDWaxigwfZYuYmDZ6xtrNwNlidKZwkSrDaY9n90tdrJTV5Umk+wP1fZscGptmKFXHsXMDEVZ+Q6A== + dependencies: + "@braintree/sanitize-url" "^7.0.1" + "@iconify/utils" "^2.1.32" + "@mermaid-js/parser" "^0.3.0" + "@types/d3" "^7.4.3" + cytoscape "^3.29.2" + cytoscape-cose-bilkent "^4.1.0" + cytoscape-fcose "^2.2.0" + d3 "^7.9.0" + d3-sankey "^0.12.3" + dagre-d3-es "7.0.11" + dayjs "^1.11.10" + dompurify "^3.2.1" + katex "^0.16.9" + khroma "^2.1.0" + lodash-es "^4.17.21" + marked "^13.0.2" + roughjs "^4.6.6" + stylis "^4.3.1" + ts-dedent "^2.2.0" + uuid "^9.0.1" + methods@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" @@ -7974,6 +8780,16 @@ mkdirp@^1.0.3: resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== +mlly@^1.7.3: + version "1.7.3" + resolved "https://registry.npmmirror.com/mlly/-/mlly-1.7.3.tgz#d86c0fcd8ad8e16395eb764a5f4b831590cee48c" + integrity sha512-xUsx5n/mN0uQf4V548PKQ+YShA4/IW0KI1dZhrNrPCLG+xizETbHTkOa1f8/xut9JRPp8kQuMnz0oqwkTiLo/A== + dependencies: + acorn "^8.14.0" + pathe "^1.1.2" + pkg-types "^1.2.1" + ufo "^1.5.4" + mockjs@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/mockjs/-/mockjs-1.1.0.tgz#e6a0c378e91906dbaff20911cc0273b3c7d75b06" @@ -8001,7 +8817,7 @@ ms@2.1.2: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== -ms@2.1.3, ms@^2.1.1: +ms@2.1.3, ms@^2.1.1, ms@^2.1.3: version "2.1.3" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== @@ -8132,6 +8948,19 @@ ngx-echarts@17.2.0: dependencies: tslib "^2.3.0" +ngx-markdown@19.0.0: + version "19.0.0" + resolved "https://registry.npmmirror.com/ngx-markdown/-/ngx-markdown-19.0.0.tgz#e1bad3111a4545a3e65721381aecb2c05fb71197" + integrity sha512-/UDTYxK2sbG9LjeuPfqErCg9gbT1O64Rnqvs9qgvK70X//gEVCMStNUi1zYIqw/SLRk19Rk48DZMgPiFRbgb1Q== + dependencies: + tslib "^2.3.0" + optionalDependencies: + clipboard "^2.0.11" + emoji-toolkit ">= 8.0.0 < 10.0.0" + katex "^0.16.0" + mermaid ">= 10.6.0 < 12.0.0" + prismjs "^1.28.0" + ngx-slick-carousel@17.0.0: version "17.0.0" resolved "https://registry.yarnpkg.com/ngx-slick-carousel/-/ngx-slick-carousel-17.0.0.tgz#3123f44a05f6608d69434ce92138fc52759508e6" @@ -8741,6 +9570,11 @@ package-json-from-dist@^1.0.0: resolved "https://registry.yarnpkg.com/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz#e501cd3094b278495eb4258d4c9f6d5ac3019f00" integrity sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw== +package-manager-detector@^0.2.0: + version "0.2.8" + resolved "https://registry.npmmirror.com/package-manager-detector/-/package-manager-detector-0.2.8.tgz#f5ace2dbd37666af54e5acec11bc37c8450f72d0" + integrity sha512-ts9KSdroZisdvKMWVAVCXiKqnqNfXz4+IbrBG8/BWx/TR5le+jfenvoBuIZ6UWM9nz47W7AbD9qYfAwfWMIwzA== + pacote@17.0.6: version "17.0.6" resolved "https://registry.yarnpkg.com/pacote/-/pacote-17.0.6.tgz#874bb59cda5d44ab784d0b6530fcb4a7d9b76a60" @@ -8845,6 +9679,11 @@ pascalcase@^0.1.1: resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" integrity sha512-XHXfu/yOQRy9vYOtUDVMN60OEJjW013GoObG1o+xwQTpB9eYJX/BjXMsdW13ZDPruFhYYn0AG22w0xgQMwl3Nw== +path-data-parser@0.1.0, path-data-parser@^0.1.0: + version "0.1.0" + resolved "https://registry.npmmirror.com/path-data-parser/-/path-data-parser-0.1.0.tgz#8f5ba5cc70fc7becb3dcefaea08e2659aba60b8c" + integrity sha512-NOnmBpt5Y2RWbuv0LMzsayp3lVylAHLPUTut412ZA3l+C4uw4ZVkQbjShYCQ8TCpUMdPapr4YjUqLYD6v68j+w== + path-dirname@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" @@ -8915,6 +9754,11 @@ path-type@^4.0.0: resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== +pathe@^1.1.2: + version "1.1.2" + resolved "https://registry.npmmirror.com/pathe/-/pathe-1.1.2.tgz#6c4cb47a945692e48a1ddd6e4094d170516437ec" + integrity sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ== + performance-now@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" @@ -8986,6 +9830,15 @@ pkg-dir@^7.0.0: dependencies: find-up "^6.3.0" +pkg-types@^1.2.1: + version "1.3.0" + resolved "https://registry.npmmirror.com/pkg-types/-/pkg-types-1.3.0.tgz#53d915eb99485798c554ad8eb2dc2af7c03006eb" + integrity sha512-kS7yWjVFCkIw9hqdJBoMxDdzEngmkr5FXeWZZfQ6GoYacjVnsW6l2CcYW/0ThD0vF4LPJgVYnrg4d0uuhwYQbg== + dependencies: + confbox "^0.1.8" + mlly "^1.7.3" + pathe "^1.1.2" + plyr@^3.7.8: version "3.7.8" resolved "https://registry.yarnpkg.com/plyr/-/plyr-3.7.8.tgz#b79bccc23687705b5d9a283b2a88c124bf7471ed" @@ -8997,6 +9850,19 @@ plyr@^3.7.8: rangetouch "^2.0.1" url-polyfill "^1.1.12" +points-on-curve@0.2.0, points-on-curve@^0.2.0: + version "0.2.0" + resolved "https://registry.npmmirror.com/points-on-curve/-/points-on-curve-0.2.0.tgz#7dbb98c43791859434284761330fa893cb81b4d1" + integrity sha512-0mYKnYYe9ZcqMCWhUjItv/oHjvgEsfKvnUTg8sAtnHr3GVy7rGkXCb6d5cSyqrWqL4k81b9CPg3urd+T7aop3A== + +points-on-path@^0.2.1: + version "0.2.1" + resolved "https://registry.npmmirror.com/points-on-path/-/points-on-path-0.2.1.tgz#553202b5424c53bed37135b318858eacff85dd52" + integrity sha512-25ClnWWuw7JbWZcgqY/gJ4FQWadKxGWk+3kR/7kD0tCaDtPPMj7oHu2ToLaVhfpnHrZzYby2w6tUA0eOIuUg8g== + dependencies: + path-data-parser "0.1.0" + points-on-curve "0.2.0" + posix-character-classes@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" @@ -9227,6 +10093,11 @@ pretty-format@^29.7.0: ansi-styles "^5.0.0" react-is "^18.0.0" +prismjs@^1.28.0: + version "1.29.0" + resolved "https://registry.npmmirror.com/prismjs/-/prismjs-1.29.0.tgz#f113555a8fa9b57c35e637bba27509dcf802dd12" + integrity sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q== + proc-log@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/proc-log/-/proc-log-3.0.0.tgz#fb05ef83ccd64fd7b20bbe9c8c1070fc08338dd8" @@ -9771,6 +10642,11 @@ rimraf@^3.0.2: dependencies: glob "^7.1.3" +robust-predicates@^3.0.2: + version "3.0.2" + resolved "https://registry.npmmirror.com/robust-predicates/-/robust-predicates-3.0.2.tgz#d5b28528c4824d20fc48df1928d41d9efa1ad771" + integrity sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg== + rollup@^4.2.0: version "4.18.1" resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.18.1.tgz#18a606df5e76ca53b8a69f2d8eab256d69dda851" @@ -9796,6 +10672,16 @@ rollup@^4.2.0: "@rollup/rollup-win32-x64-msvc" "4.18.1" fsevents "~2.3.2" +roughjs@^4.6.6: + version "4.6.6" + resolved "https://registry.npmmirror.com/roughjs/-/roughjs-4.6.6.tgz#1059f49a5e0c80dee541a005b20cc322b222158b" + integrity sha512-ZUz/69+SYpFN/g/lUlo2FXcIjRkSu3nDarreVdGGndHEBJ6cXPdKguS8JGxwj5HA5xIbVKSmLgr5b3AWxtRfvQ== + dependencies: + hachure-fill "^0.5.2" + path-data-parser "^0.1.0" + points-on-curve "^0.2.0" + points-on-path "^0.2.1" + run-async@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/run-async/-/run-async-3.0.0.tgz#42a432f6d76c689522058984384df28be379daad" @@ -9808,6 +10694,11 @@ run-parallel@^1.1.9: dependencies: queue-microtask "^1.2.2" +rw@1: + version "1.3.3" + resolved "https://registry.npmmirror.com/rw/-/rw-1.3.3.tgz#3f862dfa91ab766b14885ef4d01124bfda074fb4" + integrity sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ== + rxjs@7.8.1, rxjs@^7.8.1: version "7.8.1" resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.8.1.tgz#6f6f3d99ea8044291efd92e7c7fcf562c4057543" @@ -9913,6 +10804,11 @@ select-hose@^2.0.0: resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca" integrity sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg== +select@^1.1.2: + version "1.1.2" + resolved "https://registry.npmmirror.com/select/-/select-1.1.2.tgz#0e7350acdec80b1108528786ec1d4418d11b396d" + integrity sha512-OwpTSOfy6xSs1+pwcNrv0RBMOzI39Lp3qQKUTPVVPRjCdNa5JH/oPRiqsesIskK8TVgmRiHwO4KXlV2Li9dANA== + selenium-webdriver@3.6.0, selenium-webdriver@^3.0.1: version "3.6.0" resolved "https://registry.yarnpkg.com/selenium-webdriver/-/selenium-webdriver-3.6.0.tgz#2ba87a1662c020b8988c981ae62cb2a01298eafc" @@ -10830,6 +11726,11 @@ stylelint@^9.10.1: svg-tags "^1.0.0" table "^5.0.0" +stylis@^4.3.1: + version "4.3.4" + resolved "https://registry.npmmirror.com/stylis/-/stylis-4.3.4.tgz#ca5c6c4a35c4784e4e93a2a24dc4e9fa075250a4" + integrity sha512-osIBl6BGUmSfDkyH2mB7EFvCJntXDrLhKjHTRj/rK6xLH0yuPrHULDRQzKokSOD4VoorhtKpfcfW1GAntu8now== + sugarss@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/sugarss/-/sugarss-2.0.0.tgz#ddd76e0124b297d40bf3cca31c8b22ecb43bc61d" @@ -11040,6 +11941,16 @@ thunky@^1.0.2: resolved "https://registry.yarnpkg.com/thunky/-/thunky-1.1.0.tgz#5abaf714a9405db0504732bbccd2cedd9ef9537d" integrity sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA== +tiny-emitter@^2.0.0: + version "2.1.0" + resolved "https://registry.npmmirror.com/tiny-emitter/-/tiny-emitter-2.1.0.tgz#1d1a56edfc51c43e863cbb5382a72330e3555423" + integrity sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q== + +tinyexec@^0.3.0: + version "0.3.2" + resolved "https://registry.npmmirror.com/tinyexec/-/tinyexec-0.3.2.tgz#941794e657a85e496577995c6eef66f53f42b3d2" + integrity sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA== + tmp@0.0.30: version "0.0.30" resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.30.tgz#72419d4a8be7d6ce75148fd8b324e593a711c2ed" @@ -11149,6 +12060,11 @@ ts-api-utils@^1.3.0: resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.3.0.tgz#4b490e27129f1e8e686b45cc4ab63714dc60eea1" integrity sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ== +ts-dedent@^2.2.0: + version "2.2.0" + resolved "https://registry.npmmirror.com/ts-dedent/-/ts-dedent-2.2.0.tgz#39e4bd297cd036292ae2394eb3412be63f563bb5" + integrity sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ== + ts-node@10.9.1: version "10.9.1" resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.9.1.tgz#e73de9102958af9e1f0b168a6ff320e25adcff4b" @@ -11332,6 +12248,11 @@ ua-parser-js@^0.7.30: resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.38.tgz#f497d8a4dc1fec6e854e5caa4b2f9913422ef054" integrity sha512-fYmIy7fKTSFAhG3fuPlubeGaMoAd6r0rSnfEsO5nEY55i26KSLt9EH7PLQiiqPUhNqYIJvSkTy1oArIcXAbPbA== +ufo@^1.5.4: + version "1.5.4" + resolved "https://registry.npmmirror.com/ufo/-/ufo-1.5.4.tgz#16d6949674ca0c9e0fbbae1fa20a71d7b1ded754" + integrity sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ== + unbox-primitive@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.2.tgz#29032021057d5e6cdbd08c5129c226dff8ed6f9e" @@ -11544,6 +12465,11 @@ uuid@^8.3.2: resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== +uuid@^9.0.1: + version "9.0.1" + resolved "https://registry.npmmirror.com/uuid/-/uuid-9.0.1.tgz#e188d4c8853cc722220392c424cd637f32293f30" + integrity sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA== + v8-compile-cache-lib@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf" @@ -11627,6 +12553,41 @@ void-elements@^2.0.0: resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-2.0.1.tgz#c066afb582bb1cb4128d60ea92392e94d5e9dbec" integrity sha512-qZKX4RnBzH2ugr8Lxa7x+0V6XD9Sb/ouARtiasEQCHB1EVU4NXtmHsDDrx1dO4ne5fc3J6EW05BP1Dl0z0iung== +vscode-jsonrpc@8.2.0: + version "8.2.0" + resolved "https://registry.npmmirror.com/vscode-jsonrpc/-/vscode-jsonrpc-8.2.0.tgz#f43dfa35fb51e763d17cd94dcca0c9458f35abf9" + integrity sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA== + +vscode-languageserver-protocol@3.17.5: + version "3.17.5" + resolved "https://registry.npmmirror.com/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.5.tgz#864a8b8f390835572f4e13bd9f8313d0e3ac4bea" + integrity sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg== + dependencies: + vscode-jsonrpc "8.2.0" + vscode-languageserver-types "3.17.5" + +vscode-languageserver-textdocument@~1.0.11: + version "1.0.12" + resolved "https://registry.npmmirror.com/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.12.tgz#457ee04271ab38998a093c68c2342f53f6e4a631" + integrity sha512-cxWNPesCnQCcMPeenjKKsOCKQZ/L6Tv19DTRIGuLWe32lyzWhihGVJ/rcckZXJxfdKCFvRLS3fpBIsV/ZGX4zA== + +vscode-languageserver-types@3.17.5: + version "3.17.5" + resolved "https://registry.npmmirror.com/vscode-languageserver-types/-/vscode-languageserver-types-3.17.5.tgz#3273676f0cf2eab40b3f44d085acbb7f08a39d8a" + integrity sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg== + +vscode-languageserver@~9.0.1: + version "9.0.1" + resolved "https://registry.npmmirror.com/vscode-languageserver/-/vscode-languageserver-9.0.1.tgz#500aef82097eb94df90d008678b0b6b5f474015b" + integrity sha512-woByF3PDpkHFUreUa7Hos7+pUWdeWMXRd26+ZX2A8cFx6v/JPTtd4/uN0/jB6XQHYaOlHbio03NTHCqrgG5n7g== + dependencies: + vscode-languageserver-protocol "3.17.5" + +vscode-uri@~3.0.8: + version "3.0.8" + resolved "https://registry.npmmirror.com/vscode-uri/-/vscode-uri-3.0.8.tgz#1770938d3e72588659a172d0fd4642780083ff9f" + integrity sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw== + watchpack@2.4.0: version "2.4.0" resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.4.0.tgz#fa33032374962c78113f93c7f2fb4c54c9862a5d"