mirror of
https://github.com/OneUptime/oneuptime.git
synced 2026-04-06 00:32:12 +02:00
feat: Add Domain Monitor functionality with WHOIS integration
- Updated package.json to include whois-json dependency. - Created DomainMonitorCriteria class for evaluating domain monitoring criteria. - Added DomainMonitorResponse interface to define the structure of domain monitoring responses. - Introduced MonitorStepDomainMonitor interface and utility for managing domain monitor steps. - Developed DomainMonitorStepForm component for user input on domain monitoring settings. - Implemented DomainMonitorView component to display monitoring results and details. - Added DomainMonitorUtil class for querying domain information using WHOIS data. - Included parsing methods for name servers and domain status in DomainMonitorUtil.
This commit is contained in:
142
Common/Server/Utils/Monitor/Criteria/DomainMonitorCriteria.ts
Normal file
142
Common/Server/Utils/Monitor/Criteria/DomainMonitorCriteria.ts
Normal file
@@ -0,0 +1,142 @@
|
||||
import DataToProcess from "../DataToProcess";
|
||||
import CompareCriteria from "./CompareCriteria";
|
||||
import {
|
||||
CheckOn,
|
||||
CriteriaFilter,
|
||||
FilterType,
|
||||
} from "../../../../Types/Monitor/CriteriaFilter";
|
||||
import DomainMonitorResponse from "../../../../Types/Monitor/DomainMonitor/DomainMonitorResponse";
|
||||
import ProbeMonitorResponse from "../../../../Types/Probe/ProbeMonitorResponse";
|
||||
import CaptureSpan from "../../Telemetry/CaptureSpan";
|
||||
|
||||
export default class DomainMonitorCriteria {
|
||||
@CaptureSpan()
|
||||
public static async isMonitorInstanceCriteriaFilterMet(input: {
|
||||
dataToProcess: DataToProcess;
|
||||
criteriaFilter: CriteriaFilter;
|
||||
}): Promise<string | null> {
|
||||
let threshold: number | string | undefined | null =
|
||||
input.criteriaFilter.value;
|
||||
|
||||
const dataToProcess: ProbeMonitorResponse =
|
||||
input.dataToProcess as ProbeMonitorResponse;
|
||||
|
||||
const domainResponse: DomainMonitorResponse | undefined =
|
||||
dataToProcess.domainResponse;
|
||||
|
||||
// Check domain expires in days
|
||||
if (input.criteriaFilter.checkOn === CheckOn.DomainExpiresDaysIn) {
|
||||
threshold = CompareCriteria.convertToNumber(threshold);
|
||||
|
||||
if (threshold === null || threshold === undefined) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!domainResponse?.expiresDate) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const expiresDate: Date = new Date(domainResponse.expiresDate);
|
||||
const now: Date = new Date();
|
||||
const diffMs: number = expiresDate.getTime() - now.getTime();
|
||||
const diffDays: number = Math.ceil(diffMs / (1000 * 60 * 60 * 24));
|
||||
|
||||
return CompareCriteria.compareCriteriaNumbers({
|
||||
value: diffDays,
|
||||
threshold: threshold as number,
|
||||
criteriaFilter: input.criteriaFilter,
|
||||
});
|
||||
}
|
||||
|
||||
// Check domain registrar
|
||||
if (input.criteriaFilter.checkOn === CheckOn.DomainRegistrar) {
|
||||
if (!domainResponse?.registrar) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return CompareCriteria.compareCriteriaStrings({
|
||||
value: domainResponse.registrar,
|
||||
threshold: String(threshold),
|
||||
criteriaFilter: input.criteriaFilter,
|
||||
});
|
||||
}
|
||||
|
||||
// Check domain name server
|
||||
if (input.criteriaFilter.checkOn === CheckOn.DomainNameServer) {
|
||||
if (
|
||||
!domainResponse?.nameServers ||
|
||||
domainResponse.nameServers.length === 0
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Check if any name server matches the criteria
|
||||
for (const nameServer of domainResponse.nameServers) {
|
||||
const result: string | null = CompareCriteria.compareCriteriaStrings({
|
||||
value: nameServer,
|
||||
threshold: String(threshold),
|
||||
criteriaFilter: input.criteriaFilter,
|
||||
});
|
||||
|
||||
if (result) {
|
||||
return `Domain name server: ${result}`;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// Check domain status code
|
||||
if (input.criteriaFilter.checkOn === CheckOn.DomainStatusCode) {
|
||||
if (
|
||||
!domainResponse?.domainStatus ||
|
||||
domainResponse.domainStatus.length === 0
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Check if any status matches the criteria
|
||||
for (const status of domainResponse.domainStatus) {
|
||||
const result: string | null = CompareCriteria.compareCriteriaStrings({
|
||||
value: status,
|
||||
threshold: String(threshold),
|
||||
criteriaFilter: input.criteriaFilter,
|
||||
});
|
||||
|
||||
if (result) {
|
||||
return `Domain status: ${result}`;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// Check if domain is expired
|
||||
if (input.criteriaFilter.checkOn === CheckOn.DomainIsExpired) {
|
||||
const isTrue: boolean =
|
||||
input.criteriaFilter.filterType === FilterType.True;
|
||||
const isFalse: boolean =
|
||||
input.criteriaFilter.filterType === FilterType.False;
|
||||
|
||||
if (!domainResponse?.expiresDate) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const expiresDate: Date = new Date(domainResponse.expiresDate);
|
||||
const now: Date = new Date();
|
||||
const isExpired: boolean = expiresDate.getTime() < now.getTime();
|
||||
|
||||
if (isExpired && isTrue) {
|
||||
return `Domain is expired (expired on ${domainResponse.expiresDate}).`;
|
||||
}
|
||||
|
||||
if (!isExpired && isFalse) {
|
||||
return `Domain is not expired (expires on ${domainResponse.expiresDate}).`;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,7 @@ import TraceMonitorCriteria from "./Criteria/TraceMonitorCriteria";
|
||||
import ExceptionMonitorCriteria from "./Criteria/ExceptionMonitorCriteria";
|
||||
import SnmpMonitorCriteria from "./Criteria/SnmpMonitorCriteria";
|
||||
import DnsMonitorCriteria from "./Criteria/DnsMonitorCriteria";
|
||||
import DomainMonitorCriteria from "./Criteria/DomainMonitorCriteria";
|
||||
import MonitorCriteriaMessageBuilder from "./MonitorCriteriaMessageBuilder";
|
||||
import MonitorCriteriaDataExtractor from "./MonitorCriteriaDataExtractor";
|
||||
import MonitorCriteriaMessageFormatter from "./MonitorCriteriaMessageFormatter";
|
||||
@@ -506,6 +507,18 @@ ${contextBlock}
|
||||
}
|
||||
}
|
||||
|
||||
if (input.monitor.monitorType === MonitorType.Domain) {
|
||||
const domainMonitorResult: string | null =
|
||||
await DomainMonitorCriteria.isMonitorInstanceCriteriaFilterMet({
|
||||
dataToProcess: input.dataToProcess,
|
||||
criteriaFilter: input.criteriaFilter,
|
||||
});
|
||||
|
||||
if (domainMonitorResult) {
|
||||
return domainMonitorResult;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ import SnmpMonitorResponse, {
|
||||
import DnsMonitorResponse, {
|
||||
DnsRecordResponse,
|
||||
} from "../../../Types/Monitor/DnsMonitor/DnsMonitorResponse";
|
||||
import DomainMonitorResponse from "../../../Types/Monitor/DomainMonitor/DomainMonitorResponse";
|
||||
import Typeof from "../../../Types/Typeof";
|
||||
import VMUtil from "../VM/VMAPI";
|
||||
import DataToProcess from "./DataToProcess";
|
||||
@@ -277,6 +278,26 @@ export default class MonitorTemplateUtil {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (data.monitorType === MonitorType.Domain) {
|
||||
const domainResponse: DomainMonitorResponse | undefined = (
|
||||
data.dataToProcess as ProbeMonitorResponse
|
||||
).domainResponse;
|
||||
|
||||
storageMap = {
|
||||
isOnline: (data.dataToProcess as ProbeMonitorResponse).isOnline,
|
||||
responseTimeInMs: domainResponse?.responseTimeInMs,
|
||||
failureCause: domainResponse?.failureCause,
|
||||
domainName: domainResponse?.domainName,
|
||||
registrar: domainResponse?.registrar,
|
||||
createdDate: domainResponse?.createdDate,
|
||||
updatedDate: domainResponse?.updatedDate,
|
||||
expiresDate: domainResponse?.expiresDate,
|
||||
nameServers: domainResponse?.nameServers,
|
||||
domainStatus: domainResponse?.domainStatus,
|
||||
dnssec: domainResponse?.dnssec,
|
||||
} as JSONObject;
|
||||
}
|
||||
} catch (err) {
|
||||
logger.error(err);
|
||||
}
|
||||
|
||||
@@ -67,6 +67,13 @@ export enum CheckOn {
|
||||
DnsRecordValue = "DNS Record Value",
|
||||
DnssecIsValid = "DNSSEC Is Valid",
|
||||
DnsRecordExists = "DNS Record Exists",
|
||||
|
||||
// Domain monitors.
|
||||
DomainExpiresDaysIn = "Domain Expires In Days",
|
||||
DomainRegistrar = "Domain Registrar",
|
||||
DomainNameServer = "Domain Name Server",
|
||||
DomainStatusCode = "Domain Status Code",
|
||||
DomainIsExpired = "Domain Is Expired",
|
||||
}
|
||||
|
||||
export interface ServerMonitorOptions {
|
||||
@@ -151,7 +158,8 @@ export class CriteriaFilterUtil {
|
||||
if (
|
||||
checkOn === CheckOn.IsOnline ||
|
||||
checkOn === CheckOn.SnmpIsOnline ||
|
||||
checkOn === CheckOn.DnsIsOnline
|
||||
checkOn === CheckOn.DnsIsOnline ||
|
||||
checkOn === CheckOn.DomainIsExpired
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
15
Common/Types/Monitor/DomainMonitor/DomainMonitorResponse.ts
Normal file
15
Common/Types/Monitor/DomainMonitor/DomainMonitorResponse.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
export default interface DomainMonitorResponse {
|
||||
isOnline: boolean;
|
||||
responseTimeInMs: number;
|
||||
failureCause: string;
|
||||
domainName: string;
|
||||
registrar?: string | undefined;
|
||||
registrarUrl?: string | undefined;
|
||||
createdDate?: string | undefined;
|
||||
updatedDate?: string | undefined;
|
||||
expiresDate?: string | undefined;
|
||||
nameServers?: Array<string> | undefined;
|
||||
dnssec?: string | undefined;
|
||||
domainStatus?: Array<string> | undefined;
|
||||
isTimeout?: boolean | undefined;
|
||||
}
|
||||
@@ -32,6 +32,9 @@ import MonitorStepSnmpMonitor, {
|
||||
import MonitorStepDnsMonitor, {
|
||||
MonitorStepDnsMonitorUtil,
|
||||
} from "./MonitorStepDnsMonitor";
|
||||
import MonitorStepDomainMonitor, {
|
||||
MonitorStepDomainMonitorUtil,
|
||||
} from "./MonitorStepDomainMonitor";
|
||||
import Zod, { ZodSchema } from "../../Utils/Schema/Zod";
|
||||
|
||||
export interface MonitorStepType {
|
||||
@@ -78,6 +81,9 @@ export interface MonitorStepType {
|
||||
|
||||
// DNS monitor
|
||||
dnsMonitor?: MonitorStepDnsMonitor | undefined;
|
||||
|
||||
// Domain monitor
|
||||
domainMonitor?: MonitorStepDomainMonitor | undefined;
|
||||
}
|
||||
|
||||
export default class MonitorStep extends DatabaseProperty {
|
||||
@@ -105,6 +111,7 @@ export default class MonitorStep extends DatabaseProperty {
|
||||
exceptionMonitor: undefined,
|
||||
snmpMonitor: undefined,
|
||||
dnsMonitor: undefined,
|
||||
domainMonitor: undefined,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -137,6 +144,7 @@ export default class MonitorStep extends DatabaseProperty {
|
||||
exceptionMonitor: undefined,
|
||||
snmpMonitor: undefined,
|
||||
dnsMonitor: undefined,
|
||||
domainMonitor: undefined,
|
||||
};
|
||||
|
||||
return monitorStep;
|
||||
@@ -237,6 +245,13 @@ export default class MonitorStep extends DatabaseProperty {
|
||||
return this;
|
||||
}
|
||||
|
||||
public setDomainMonitor(
|
||||
domainMonitor: MonitorStepDomainMonitor,
|
||||
): MonitorStep {
|
||||
this.data!.domainMonitor = domainMonitor;
|
||||
return this;
|
||||
}
|
||||
|
||||
public setCustomCode(customCode: string): MonitorStep {
|
||||
this.data!.customCode = customCode;
|
||||
return this;
|
||||
@@ -355,6 +370,16 @@ export default class MonitorStep extends DatabaseProperty {
|
||||
}
|
||||
}
|
||||
|
||||
if (monitorType === MonitorType.Domain) {
|
||||
if (!value.data.domainMonitor) {
|
||||
return "Domain configuration is required";
|
||||
}
|
||||
|
||||
if (!value.data.domainMonitor.domainName) {
|
||||
return "Domain name is required";
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -403,6 +428,9 @@ export default class MonitorStep extends DatabaseProperty {
|
||||
dnsMonitor: this.data.dnsMonitor
|
||||
? MonitorStepDnsMonitorUtil.toJSON(this.data.dnsMonitor)
|
||||
: undefined,
|
||||
domainMonitor: this.data.domainMonitor
|
||||
? MonitorStepDomainMonitorUtil.toJSON(this.data.domainMonitor)
|
||||
: undefined,
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -511,6 +539,9 @@ export default class MonitorStep extends DatabaseProperty {
|
||||
dnsMonitor: json["dnsMonitor"]
|
||||
? (json["dnsMonitor"] as JSONObject)
|
||||
: undefined,
|
||||
domainMonitor: json["domainMonitor"]
|
||||
? (json["domainMonitor"] as JSONObject)
|
||||
: undefined,
|
||||
}) as any;
|
||||
|
||||
return monitorStep;
|
||||
@@ -537,6 +568,7 @@ export default class MonitorStep extends DatabaseProperty {
|
||||
metricMonitor: Zod.any().optional(),
|
||||
snmpMonitor: Zod.any().optional(),
|
||||
dnsMonitor: Zod.any().optional(),
|
||||
domainMonitor: Zod.any().optional(),
|
||||
}).openapi({
|
||||
type: "object",
|
||||
example: {
|
||||
|
||||
33
Common/Types/Monitor/MonitorStepDomainMonitor.ts
Normal file
33
Common/Types/Monitor/MonitorStepDomainMonitor.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
import { JSONObject } from "../JSON";
|
||||
|
||||
export default interface MonitorStepDomainMonitor {
|
||||
domainName: string;
|
||||
timeout: number;
|
||||
retries: number;
|
||||
}
|
||||
|
||||
export class MonitorStepDomainMonitorUtil {
|
||||
public static getDefault(): MonitorStepDomainMonitor {
|
||||
return {
|
||||
domainName: "",
|
||||
timeout: 10000,
|
||||
retries: 3,
|
||||
};
|
||||
}
|
||||
|
||||
public static fromJSON(json: JSONObject): MonitorStepDomainMonitor {
|
||||
return {
|
||||
domainName: (json["domainName"] as string) || "",
|
||||
timeout: (json["timeout"] as number) || 10000,
|
||||
retries: (json["retries"] as number) || 3,
|
||||
};
|
||||
}
|
||||
|
||||
public static toJSON(monitor: MonitorStepDomainMonitor): JSONObject {
|
||||
return {
|
||||
domainName: monitor.domainName,
|
||||
timeout: monitor.timeout,
|
||||
retries: monitor.retries,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -29,6 +29,9 @@ enum MonitorType {
|
||||
|
||||
// DNS monitoring
|
||||
DNS = "DNS",
|
||||
|
||||
// Domain registration monitoring
|
||||
Domain = "Domain",
|
||||
}
|
||||
|
||||
export default MonitorType;
|
||||
@@ -58,6 +61,7 @@ export class MonitorTypeHelper {
|
||||
MonitorType.Port,
|
||||
MonitorType.DNS,
|
||||
MonitorType.SSLCertificate,
|
||||
MonitorType.Domain,
|
||||
],
|
||||
},
|
||||
{
|
||||
@@ -239,6 +243,13 @@ export class MonitorTypeHelper {
|
||||
"This monitor type lets you monitor DNS resolution for your domains, verify record values, and check DNSSEC validity.",
|
||||
icon: IconProp.GlobeAlt,
|
||||
},
|
||||
{
|
||||
monitorType: MonitorType.Domain,
|
||||
title: "Domain",
|
||||
description:
|
||||
"This monitor type lets you monitor domain registration health — expiry dates, registrar info, nameserver delegation, and WHOIS status.",
|
||||
icon: IconProp.Globe,
|
||||
},
|
||||
];
|
||||
|
||||
return monitorTypeProps;
|
||||
@@ -285,7 +296,8 @@ export class MonitorTypeHelper {
|
||||
monitorType === MonitorType.SyntheticMonitor ||
|
||||
monitorType === MonitorType.CustomJavaScriptCode ||
|
||||
monitorType === MonitorType.SNMP ||
|
||||
monitorType === MonitorType.DNS;
|
||||
monitorType === MonitorType.DNS ||
|
||||
monitorType === MonitorType.Domain;
|
||||
return isProbeableMonitor;
|
||||
}
|
||||
|
||||
@@ -308,6 +320,7 @@ export class MonitorTypeHelper {
|
||||
MonitorType.Exceptions,
|
||||
MonitorType.SNMP,
|
||||
MonitorType.DNS,
|
||||
MonitorType.Domain,
|
||||
];
|
||||
}
|
||||
|
||||
@@ -341,7 +354,8 @@ export class MonitorTypeHelper {
|
||||
monitorType === MonitorType.SyntheticMonitor ||
|
||||
monitorType === MonitorType.CustomJavaScriptCode ||
|
||||
monitorType === MonitorType.SNMP ||
|
||||
monitorType === MonitorType.DNS
|
||||
monitorType === MonitorType.DNS ||
|
||||
monitorType === MonitorType.Domain
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import SslMonitorResponse from "../Monitor/SSLMonitor/SslMonitorResponse";
|
||||
import SyntheticMonitorResponse from "../Monitor/SyntheticMonitors/SyntheticMonitorResponse";
|
||||
import SnmpMonitorResponse from "../Monitor/SnmpMonitor/SnmpMonitorResponse";
|
||||
import DnsMonitorResponse from "../Monitor/DnsMonitor/DnsMonitorResponse";
|
||||
import DomainMonitorResponse from "../Monitor/DomainMonitor/DomainMonitorResponse";
|
||||
import MonitorEvaluationSummary from "../Monitor/MonitorEvaluationSummary";
|
||||
import ObjectID from "../ObjectID";
|
||||
import Port from "../Port";
|
||||
@@ -32,6 +33,7 @@ export default interface ProbeMonitorResponse {
|
||||
customCodeMonitorResponse?: CustomCodeMonitorResponse | undefined;
|
||||
snmpResponse?: SnmpMonitorResponse | undefined;
|
||||
dnsResponse?: DnsMonitorResponse | undefined;
|
||||
domainResponse?: DomainMonitorResponse | undefined;
|
||||
monitoredAt: Date;
|
||||
isTimeout?: boolean | undefined;
|
||||
ingestedAt?: Date | undefined;
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
import React, { FunctionComponent, ReactElement, useState } from "react";
|
||||
import MonitorStepDomainMonitor from "Common/Types/Monitor/MonitorStepDomainMonitor";
|
||||
import Input, { InputType } from "Common/UI/Components/Input/Input";
|
||||
import FieldLabelElement from "Common/UI/Components/Forms/Fields/FieldLabel";
|
||||
import Button, { ButtonStyleType } from "Common/UI/Components/Button/Button";
|
||||
|
||||
export interface ComponentProps {
|
||||
monitorStepDomainMonitor: MonitorStepDomainMonitor;
|
||||
onChange: (value: MonitorStepDomainMonitor) => void;
|
||||
}
|
||||
|
||||
const DomainMonitorStepForm: FunctionComponent<ComponentProps> = (
|
||||
props: ComponentProps,
|
||||
): ReactElement => {
|
||||
const [showAdvancedOptions, setShowAdvancedOptions] =
|
||||
useState<boolean>(false);
|
||||
|
||||
return (
|
||||
<div className="space-y-5">
|
||||
<div>
|
||||
<FieldLabelElement
|
||||
title="Domain Name"
|
||||
description="The domain name to monitor (e.g. example.com)"
|
||||
required={true}
|
||||
/>
|
||||
<Input
|
||||
initialValue={props.monitorStepDomainMonitor.domainName}
|
||||
placeholder="example.com"
|
||||
onChange={(value: string) => {
|
||||
props.onChange({
|
||||
...props.monitorStepDomainMonitor,
|
||||
domainName: value,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{!showAdvancedOptions && (
|
||||
<div className="mt-1 -ml-3">
|
||||
<Button
|
||||
title="Advanced: Timeout and Retries"
|
||||
buttonStyle={ButtonStyleType.SECONDARY_LINK}
|
||||
onClick={() => {
|
||||
setShowAdvancedOptions(true);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{showAdvancedOptions && (
|
||||
<div className="space-y-4 border p-4 rounded-md bg-gray-50">
|
||||
<h4 className="font-medium">Advanced Options</h4>
|
||||
|
||||
<div>
|
||||
<FieldLabelElement
|
||||
title="Timeout (ms)"
|
||||
description="How long to wait for a WHOIS response before timing out"
|
||||
required={false}
|
||||
/>
|
||||
<Input
|
||||
initialValue={
|
||||
props.monitorStepDomainMonitor.timeout?.toString() || "10000"
|
||||
}
|
||||
placeholder="10000"
|
||||
type={InputType.NUMBER}
|
||||
onChange={(value: string) => {
|
||||
props.onChange({
|
||||
...props.monitorStepDomainMonitor,
|
||||
timeout: parseInt(value) || 10000,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<FieldLabelElement
|
||||
title="Retries"
|
||||
description="Number of times to retry on failure"
|
||||
required={false}
|
||||
/>
|
||||
<Input
|
||||
initialValue={
|
||||
props.monitorStepDomainMonitor.retries?.toString() || "3"
|
||||
}
|
||||
placeholder="3"
|
||||
type={InputType.NUMBER}
|
||||
onChange={(value: string) => {
|
||||
props.onChange({
|
||||
...props.monitorStepDomainMonitor,
|
||||
retries: parseInt(value) || 3,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default DomainMonitorStepForm;
|
||||
@@ -79,6 +79,10 @@ import DnsMonitorStepForm from "./DnsMonitor/DnsMonitorStepForm";
|
||||
import MonitorStepDnsMonitor, {
|
||||
MonitorStepDnsMonitorUtil,
|
||||
} from "Common/Types/Monitor/MonitorStepDnsMonitor";
|
||||
import DomainMonitorStepForm from "./DomainMonitor/DomainMonitorStepForm";
|
||||
import MonitorStepDomainMonitor, {
|
||||
MonitorStepDomainMonitorUtil,
|
||||
} from "Common/Types/Monitor/MonitorStepDomainMonitor";
|
||||
|
||||
export interface ComponentProps {
|
||||
monitorStatusDropdownOptions: Array<DropdownOption>;
|
||||
@@ -812,6 +816,24 @@ return {
|
||||
</Card>
|
||||
)}
|
||||
|
||||
{props.monitorType === MonitorType.Domain && (
|
||||
<Card
|
||||
title="Domain Monitor Configuration"
|
||||
description="Configure the domain registration monitoring settings"
|
||||
>
|
||||
<DomainMonitorStepForm
|
||||
monitorStepDomainMonitor={
|
||||
monitorStep.data?.domainMonitor ||
|
||||
MonitorStepDomainMonitorUtil.getDefault()
|
||||
}
|
||||
onChange={(value: MonitorStepDomainMonitor) => {
|
||||
monitorStep.setDomainMonitor(value);
|
||||
props.onChange?.(MonitorStep.clone(monitorStep));
|
||||
}}
|
||||
/>
|
||||
</Card>
|
||||
)}
|
||||
|
||||
{/* Code Monitor Section */}
|
||||
{isCodeMonitor && (
|
||||
<Card
|
||||
|
||||
@@ -310,6 +310,20 @@ const MonitorStepElement: FunctionComponent<ComponentProps> = (
|
||||
placeholder: "0",
|
||||
},
|
||||
];
|
||||
} else if (props.monitorType === MonitorType.Domain) {
|
||||
fields = [
|
||||
{
|
||||
key: "domainMonitor",
|
||||
title: "Domain Name",
|
||||
description: "The domain name being monitored via WHOIS.",
|
||||
fieldType: FieldType.Element,
|
||||
placeholder: "No data entered",
|
||||
getElement: (item: MonitorStepType): ReactElement => {
|
||||
const domainMonitor: any = item.domainMonitor;
|
||||
return <p>{domainMonitor?.domainName || "-"}</p>;
|
||||
},
|
||||
},
|
||||
];
|
||||
} else if (props.monitorType === MonitorType.Logs) {
|
||||
logFields = [];
|
||||
|
||||
|
||||
@@ -0,0 +1,172 @@
|
||||
import OneUptimeDate from "Common/Types/Date";
|
||||
import ProbeMonitorResponse from "Common/Types/Probe/ProbeMonitorResponse";
|
||||
import DomainMonitorResponse from "Common/Types/Monitor/DomainMonitor/DomainMonitorResponse";
|
||||
import InfoCard from "Common/UI/Components/InfoCard/InfoCard";
|
||||
import React, { FunctionComponent, ReactElement } from "react";
|
||||
|
||||
export interface ComponentProps {
|
||||
probeMonitorResponse: ProbeMonitorResponse;
|
||||
probeName?: string | undefined;
|
||||
}
|
||||
|
||||
const DomainMonitorView: FunctionComponent<ComponentProps> = (
|
||||
props: ComponentProps,
|
||||
): ReactElement => {
|
||||
const domainResponse: DomainMonitorResponse | undefined =
|
||||
props.probeMonitorResponse?.domainResponse;
|
||||
|
||||
let responseTimeInMs: number = domainResponse?.responseTimeInMs || 0;
|
||||
|
||||
if (responseTimeInMs > 0) {
|
||||
responseTimeInMs = Math.round(responseTimeInMs);
|
||||
}
|
||||
|
||||
type FormatDateText = (dateStr: string | undefined) => string;
|
||||
|
||||
const formatDateText: FormatDateText = (
|
||||
dateStr: string | undefined,
|
||||
): string => {
|
||||
if (!dateStr) {
|
||||
return "-";
|
||||
}
|
||||
try {
|
||||
const date: Date = new Date(dateStr);
|
||||
return OneUptimeDate.getDateAsUserFriendlyLocalFormattedString(date);
|
||||
} catch {
|
||||
return dateStr;
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="space-y-5">
|
||||
<div className="flex space-x-3">
|
||||
<InfoCard
|
||||
className="w-1/5 shadow-none border-2 border-gray-100"
|
||||
title="Probe"
|
||||
value={props.probeName || "-"}
|
||||
/>
|
||||
<InfoCard
|
||||
className="w-1/5 shadow-none border-2 border-gray-100"
|
||||
title="Status"
|
||||
value={props.probeMonitorResponse.isOnline ? "Online" : "Offline"}
|
||||
/>
|
||||
<InfoCard
|
||||
className="w-1/5 shadow-none border-2 border-gray-100"
|
||||
title="Response Time"
|
||||
value={responseTimeInMs ? responseTimeInMs + " ms" : "-"}
|
||||
/>
|
||||
<InfoCard
|
||||
className="w-1/5 shadow-none border-2 border-gray-100"
|
||||
title="Expires At"
|
||||
value={formatDateText(domainResponse?.expiresDate)}
|
||||
/>
|
||||
<InfoCard
|
||||
className="w-1/5 shadow-none border-2 border-gray-100"
|
||||
title="Monitored At"
|
||||
value={
|
||||
props.probeMonitorResponse?.monitoredAt
|
||||
? OneUptimeDate.getDateAsUserFriendlyLocalFormattedString(
|
||||
props.probeMonitorResponse.monitoredAt,
|
||||
)
|
||||
: "-"
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="flex space-x-3">
|
||||
<InfoCard
|
||||
className="w-1/3 shadow-none border-2 border-gray-100"
|
||||
title="Registrar"
|
||||
value={domainResponse?.registrar || "-"}
|
||||
/>
|
||||
<InfoCard
|
||||
className="w-1/3 shadow-none border-2 border-gray-100"
|
||||
title="Created"
|
||||
value={formatDateText(domainResponse?.createdDate)}
|
||||
/>
|
||||
<InfoCard
|
||||
className="w-1/3 shadow-none border-2 border-gray-100"
|
||||
title="DNSSEC"
|
||||
value={domainResponse?.dnssec || "-"}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{props.probeMonitorResponse.failureCause && (
|
||||
<div className="flex space-x-3">
|
||||
<InfoCard
|
||||
className="w-full shadow-none border-2 border-gray-100"
|
||||
title="Error"
|
||||
value={props.probeMonitorResponse.failureCause?.toString() || "-"}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Name Servers Section */}
|
||||
{domainResponse?.nameServers && domainResponse.nameServers.length > 0 && (
|
||||
<div className="space-y-3">
|
||||
<h3 className="text-sm font-medium text-gray-700">Name Servers</h3>
|
||||
<div className="border rounded-md overflow-hidden">
|
||||
<table className="min-w-full divide-y divide-gray-200">
|
||||
<thead className="bg-gray-50">
|
||||
<tr>
|
||||
<th className="px-4 py-2 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
|
||||
Name Server
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody className="bg-white divide-y divide-gray-200">
|
||||
{domainResponse.nameServers.map(
|
||||
(ns: string, index: number) => {
|
||||
return (
|
||||
<tr key={index}>
|
||||
<td className="px-4 py-2 text-sm text-gray-900 font-mono">
|
||||
{ns}
|
||||
</td>
|
||||
</tr>
|
||||
);
|
||||
},
|
||||
)}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Domain Status Section */}
|
||||
{domainResponse?.domainStatus &&
|
||||
domainResponse.domainStatus.length > 0 && (
|
||||
<div className="space-y-3">
|
||||
<h3 className="text-sm font-medium text-gray-700">
|
||||
Domain Status Codes
|
||||
</h3>
|
||||
<div className="border rounded-md overflow-hidden">
|
||||
<table className="min-w-full divide-y divide-gray-200">
|
||||
<thead className="bg-gray-50">
|
||||
<tr>
|
||||
<th className="px-4 py-2 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
|
||||
Status
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody className="bg-white divide-y divide-gray-200">
|
||||
{domainResponse.domainStatus.map(
|
||||
(status: string, index: number) => {
|
||||
return (
|
||||
<tr key={index}>
|
||||
<td className="px-4 py-2 text-sm text-gray-900 font-mono">
|
||||
{status}
|
||||
</td>
|
||||
</tr>
|
||||
);
|
||||
},
|
||||
)}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default DomainMonitorView;
|
||||
@@ -8,6 +8,7 @@ import SyntheticMonitorView from "./SyntheticMonitorView";
|
||||
import WebsiteMonitorSummaryView from "./WebsiteMonitorView";
|
||||
import SnmpMonitorView from "./SnmpMonitorView";
|
||||
import DnsMonitorView from "./DnsMonitorView";
|
||||
import DomainMonitorView from "./DomainMonitorView";
|
||||
import IncomingMonitorRequest from "Common/Types/Monitor/IncomingMonitor/IncomingMonitorRequest";
|
||||
import IncomingEmailMonitorRequest from "Common/Types/Monitor/IncomingEmailMonitor/IncomingEmailMonitorRequest";
|
||||
import MonitorType, {
|
||||
@@ -131,6 +132,15 @@ const SummaryInfo: FunctionComponent<ComponentProps> = (
|
||||
);
|
||||
}
|
||||
|
||||
if (props.monitorType === MonitorType.Domain) {
|
||||
summaryComponent = (
|
||||
<DomainMonitorView
|
||||
probeMonitorResponse={probeMonitorResponse}
|
||||
probeName={props.probeName}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div key={key} className="space-y-6">
|
||||
{summaryComponent}
|
||||
|
||||
@@ -295,6 +295,18 @@ export default class CriteriaFilterUtil {
|
||||
});
|
||||
}
|
||||
|
||||
if (monitorType === MonitorType.Domain) {
|
||||
options = options.filter((i: DropdownOption) => {
|
||||
return (
|
||||
i.value === CheckOn.DomainExpiresDaysIn ||
|
||||
i.value === CheckOn.DomainRegistrar ||
|
||||
i.value === CheckOn.DomainNameServer ||
|
||||
i.value === CheckOn.DomainStatusCode ||
|
||||
i.value === CheckOn.DomainIsExpired
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
@@ -570,6 +582,40 @@ export default class CriteriaFilterUtil {
|
||||
});
|
||||
}
|
||||
|
||||
if (checkOn === CheckOn.DomainExpiresDaysIn) {
|
||||
options = options.filter((i: DropdownOption) => {
|
||||
return (
|
||||
i.value === FilterType.GreaterThan ||
|
||||
i.value === FilterType.LessThan ||
|
||||
i.value === FilterType.LessThanOrEqualTo ||
|
||||
i.value === FilterType.GreaterThanOrEqualTo
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
if (
|
||||
checkOn === CheckOn.DomainRegistrar ||
|
||||
checkOn === CheckOn.DomainNameServer ||
|
||||
checkOn === CheckOn.DomainStatusCode
|
||||
) {
|
||||
options = options.filter((i: DropdownOption) => {
|
||||
return (
|
||||
i.value === FilterType.Contains ||
|
||||
i.value === FilterType.NotContains ||
|
||||
i.value === FilterType.EqualTo ||
|
||||
i.value === FilterType.NotEqualTo ||
|
||||
i.value === FilterType.StartsWith ||
|
||||
i.value === FilterType.EndsWith
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
if (checkOn === CheckOn.DomainIsExpired) {
|
||||
options = options.filter((i: DropdownOption) => {
|
||||
return i.value === FilterType.True || i.value === FilterType.False;
|
||||
});
|
||||
}
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
@@ -709,6 +755,22 @@ export default class CriteriaFilterUtil {
|
||||
return "192.168.1.1";
|
||||
}
|
||||
|
||||
if (checkOn === CheckOn.DomainExpiresDaysIn) {
|
||||
return "30";
|
||||
}
|
||||
|
||||
if (checkOn === CheckOn.DomainRegistrar) {
|
||||
return "GoDaddy";
|
||||
}
|
||||
|
||||
if (checkOn === CheckOn.DomainNameServer) {
|
||||
return "ns1.example.com";
|
||||
}
|
||||
|
||||
if (checkOn === CheckOn.DomainStatusCode) {
|
||||
return "clientTransferProhibited";
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
4
Probe/Types/whois-json.d.ts
vendored
Normal file
4
Probe/Types/whois-json.d.ts
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
declare module "whois-json" {
|
||||
function whoisJson(domain: string, options?: object): Promise<any>;
|
||||
export default whoisJson;
|
||||
}
|
||||
@@ -16,6 +16,9 @@ import MonitorStepSnmpMonitor from "Common/Types/Monitor/MonitorStepSnmpMonitor"
|
||||
import DnsMonitorUtil from "./MonitorTypes/DnsMonitor";
|
||||
import DnsMonitorResponse from "Common/Types/Monitor/DnsMonitor/DnsMonitorResponse";
|
||||
import MonitorStepDnsMonitor from "Common/Types/Monitor/MonitorStepDnsMonitor";
|
||||
import DomainMonitorUtil from "./MonitorTypes/DomainMonitor";
|
||||
import DomainMonitorResponse from "Common/Types/Monitor/DomainMonitor/DomainMonitorResponse";
|
||||
import MonitorStepDomainMonitor from "Common/Types/Monitor/MonitorStepDomainMonitor";
|
||||
import HTTPMethod from "Common/Types/API/HTTPMethod";
|
||||
import URL from "Common/Types/API/URL";
|
||||
import OneUptimeDate from "Common/Types/Date";
|
||||
@@ -546,6 +549,38 @@ export default class MonitorUtil {
|
||||
result.dnsResponse = response;
|
||||
}
|
||||
|
||||
if (monitorType === MonitorType.Domain) {
|
||||
if (!monitorStep.data?.domainMonitor) {
|
||||
result.failureCause = "Domain configuration not specified";
|
||||
return result;
|
||||
}
|
||||
|
||||
const domainConfig: MonitorStepDomainMonitor =
|
||||
monitorStep.data.domainMonitor;
|
||||
|
||||
if (!domainConfig.domainName) {
|
||||
result.failureCause = "Domain name not specified";
|
||||
return result;
|
||||
}
|
||||
|
||||
const response: DomainMonitorResponse | null =
|
||||
await DomainMonitorUtil.query(domainConfig, {
|
||||
retry: PROBE_MONITOR_RETRY_LIMIT,
|
||||
monitorId: monitorId,
|
||||
timeout: domainConfig.timeout || 10000,
|
||||
});
|
||||
|
||||
if (!response) {
|
||||
return null;
|
||||
}
|
||||
|
||||
result.isOnline = response.isOnline;
|
||||
result.isTimeout = response.isTimeout;
|
||||
result.responseTimeInMs = response.responseTimeInMs;
|
||||
result.failureCause = response.failureCause;
|
||||
result.domainResponse = response;
|
||||
}
|
||||
|
||||
// update the monitoredAt time to the current time.
|
||||
result.monitoredAt = OneUptimeDate.getCurrentDate();
|
||||
|
||||
|
||||
209
Probe/Utils/Monitors/MonitorTypes/DomainMonitor.ts
Normal file
209
Probe/Utils/Monitors/MonitorTypes/DomainMonitor.ts
Normal file
@@ -0,0 +1,209 @@
|
||||
import OnlineCheck from "../../OnlineCheck";
|
||||
import logger from "Common/Server/Utils/Logger";
|
||||
import ObjectID from "Common/Types/ObjectID";
|
||||
import Sleep from "Common/Types/Sleep";
|
||||
import MonitorStepDomainMonitor from "Common/Types/Monitor/MonitorStepDomainMonitor";
|
||||
import DomainMonitorResponse from "Common/Types/Monitor/DomainMonitor/DomainMonitorResponse";
|
||||
import whoisJson from "whois-json";
|
||||
|
||||
export interface DomainQueryOptions {
|
||||
timeout?: number | undefined;
|
||||
retry?: number | undefined;
|
||||
currentRetryCount?: number | undefined;
|
||||
monitorId?: ObjectID | undefined;
|
||||
isOnlineCheckRequest?: boolean | undefined;
|
||||
}
|
||||
|
||||
export default class DomainMonitorUtil {
|
||||
public static async query(
|
||||
config: MonitorStepDomainMonitor,
|
||||
options?: DomainQueryOptions,
|
||||
): Promise<DomainMonitorResponse | null> {
|
||||
if (!options) {
|
||||
options = {};
|
||||
}
|
||||
|
||||
if (options?.currentRetryCount === undefined) {
|
||||
options.currentRetryCount = 1;
|
||||
}
|
||||
|
||||
logger.debug(
|
||||
`Domain Query: ${options?.monitorId?.toString()} ${config.domainName} - Retry: ${options?.currentRetryCount}`,
|
||||
);
|
||||
|
||||
const startTime: [number, number] = process.hrtime();
|
||||
|
||||
try {
|
||||
const result: any = await whoisJson(config.domainName);
|
||||
|
||||
const endTime: [number, number] = process.hrtime(startTime);
|
||||
const responseTimeInMs: number = Math.ceil(
|
||||
(endTime[0] * 1000000000 + endTime[1]) / 1000000,
|
||||
);
|
||||
|
||||
// Parse WHOIS response
|
||||
const whoisData: any = Array.isArray(result) ? result[0] : result;
|
||||
|
||||
const nameServers: Array<string> = DomainMonitorUtil.parseNameServers(
|
||||
whoisData?.nameServer || whoisData?.nameServers,
|
||||
);
|
||||
|
||||
const domainStatus: Array<string> = DomainMonitorUtil.parseDomainStatus(
|
||||
whoisData?.domainStatus || whoisData?.status,
|
||||
);
|
||||
|
||||
logger.debug(
|
||||
`Domain Query success: ${options?.monitorId?.toString()} ${config.domainName} - Response Time: ${responseTimeInMs}ms`,
|
||||
);
|
||||
|
||||
return {
|
||||
isOnline: true,
|
||||
responseTimeInMs: responseTimeInMs,
|
||||
failureCause: "",
|
||||
domainName: config.domainName,
|
||||
registrar: whoisData?.registrar || whoisData?.registrarName || undefined,
|
||||
registrarUrl:
|
||||
whoisData?.registrarUrl ||
|
||||
whoisData?.registrarURL ||
|
||||
whoisData?.referralUrl ||
|
||||
undefined,
|
||||
createdDate:
|
||||
whoisData?.creationDate ||
|
||||
whoisData?.createdDate ||
|
||||
whoisData?.created ||
|
||||
undefined,
|
||||
updatedDate:
|
||||
whoisData?.updatedDate ||
|
||||
whoisData?.lastUpdated ||
|
||||
whoisData?.changed ||
|
||||
undefined,
|
||||
expiresDate:
|
||||
whoisData?.registrarRegistrationExpirationDate ||
|
||||
whoisData?.registryExpiryDate ||
|
||||
whoisData?.expirationDate ||
|
||||
whoisData?.expiresDate ||
|
||||
whoisData?.expires ||
|
||||
whoisData?.expiryDate ||
|
||||
undefined,
|
||||
nameServers: nameServers.length > 0 ? nameServers : undefined,
|
||||
dnssec: whoisData?.dnssec || whoisData?.DNSSEC || undefined,
|
||||
domainStatus: domainStatus.length > 0 ? domainStatus : undefined,
|
||||
};
|
||||
} catch (err: unknown) {
|
||||
logger.debug(
|
||||
`Domain Query error: ${options?.monitorId?.toString()} ${config.domainName}`,
|
||||
);
|
||||
logger.debug(err);
|
||||
|
||||
if (!options) {
|
||||
options = {};
|
||||
}
|
||||
|
||||
if (!options.currentRetryCount) {
|
||||
options.currentRetryCount = 0;
|
||||
}
|
||||
|
||||
if (options.currentRetryCount < (options.retry || config.retries || 3)) {
|
||||
options.currentRetryCount++;
|
||||
await Sleep.sleep(1000);
|
||||
return await DomainMonitorUtil.query(config, options);
|
||||
}
|
||||
|
||||
// Check if the probe is online
|
||||
if (!options.isOnlineCheckRequest) {
|
||||
if (!(await OnlineCheck.canProbeMonitorWebsiteMonitors())) {
|
||||
logger.error(
|
||||
`DomainMonitor - Probe is not online. Cannot query ${options?.monitorId?.toString()} ${config.domainName} - ERROR: ${err}`,
|
||||
);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
const endTime: [number, number] = process.hrtime(startTime);
|
||||
const responseTimeInMs: number = Math.ceil(
|
||||
(endTime[0] * 1000000000 + endTime[1]) / 1000000,
|
||||
);
|
||||
|
||||
// Check if timeout
|
||||
const isTimeout: boolean =
|
||||
(err as Error).message?.toLowerCase().includes("timeout") ||
|
||||
(err as Error).message?.toLowerCase().includes("timed out") ||
|
||||
(err as Error).message?.toLowerCase().includes("etimeout");
|
||||
|
||||
if (isTimeout) {
|
||||
return {
|
||||
isOnline: false,
|
||||
isTimeout: true,
|
||||
responseTimeInMs: responseTimeInMs,
|
||||
failureCause:
|
||||
"Request was tried " +
|
||||
options.currentRetryCount +
|
||||
" times and it timed out.",
|
||||
domainName: config.domainName,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
isOnline: false,
|
||||
isTimeout: false,
|
||||
responseTimeInMs: responseTimeInMs,
|
||||
failureCause: (err as Error).message || (err as Error).toString(),
|
||||
domainName: config.domainName,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private static parseNameServers(
|
||||
value: string | Array<string> | undefined,
|
||||
): Array<string> {
|
||||
if (!value) {
|
||||
return [];
|
||||
}
|
||||
|
||||
if (Array.isArray(value)) {
|
||||
return value.map((ns: string) => {
|
||||
return ns.trim().toLowerCase();
|
||||
});
|
||||
}
|
||||
|
||||
if (typeof value === "string") {
|
||||
return value
|
||||
.split(/[\s,]+/)
|
||||
.map((ns: string) => {
|
||||
return ns.trim().toLowerCase();
|
||||
})
|
||||
.filter((ns: string) => {
|
||||
return ns.length > 0;
|
||||
});
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
private static parseDomainStatus(
|
||||
value: string | Array<string> | undefined,
|
||||
): Array<string> {
|
||||
if (!value) {
|
||||
return [];
|
||||
}
|
||||
|
||||
if (Array.isArray(value)) {
|
||||
return value.map((status: string) => {
|
||||
return status.trim();
|
||||
});
|
||||
}
|
||||
|
||||
if (typeof value === "string") {
|
||||
return value
|
||||
.split(/[\n,]+/)
|
||||
.map((status: string) => {
|
||||
return status.trim();
|
||||
})
|
||||
.filter((status: string) => {
|
||||
return status.length > 0;
|
||||
});
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
}
|
||||
375
Probe/package-lock.json
generated
375
Probe/package-lock.json
generated
@@ -18,7 +18,8 @@
|
||||
"net-snmp": "^3.26.1",
|
||||
"ping": "^0.4.4",
|
||||
"playwright": "^1.57.0",
|
||||
"ts-node": "^10.9.1"
|
||||
"ts-node": "^10.9.1",
|
||||
"whois-json": "^2.0.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jest": "^27.5.2",
|
||||
@@ -288,6 +289,7 @@
|
||||
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.6.tgz",
|
||||
"integrity": "sha512-FxpRyGjrMJXh7X3wGLGhNDCRiwpWEF74sKjTLDJSG5Kyvow3QZaG0Adbqzi9ZrVjTWpsX+2cxWXD71NMg93kdw==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@ampproject/remapping": "^2.2.0",
|
||||
"@babel/code-frame": "^7.23.5",
|
||||
@@ -1279,7 +1281,8 @@
|
||||
"node_modules/@types/node": {
|
||||
"version": "17.0.45",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.45.tgz",
|
||||
"integrity": "sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw=="
|
||||
"integrity": "sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/@types/ping": {
|
||||
"version": "0.4.4",
|
||||
@@ -1366,7 +1369,6 @@
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
|
||||
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
@@ -1587,6 +1589,7 @@
|
||||
"url": "https://github.com/sponsors/ai"
|
||||
}
|
||||
],
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"caniuse-lite": "^1.0.30001565",
|
||||
"electron-to-chromium": "^1.4.601",
|
||||
@@ -1649,11 +1652,20 @@
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/camel-case": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/camel-case/-/camel-case-3.0.0.tgz",
|
||||
"integrity": "sha512-+MbKztAYHXPr1jNTSKQF52VpcFjwY5RkR7fxksV8Doo4KAYc5Fl4UJRgthBbTmEx8C54DqahhbLJkDwjI3PI/w==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"no-case": "^2.2.0",
|
||||
"upper-case": "^1.1.1"
|
||||
}
|
||||
},
|
||||
"node_modules/camelcase": {
|
||||
"version": "5.3.1",
|
||||
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
|
||||
"integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
@@ -1693,6 +1705,32 @@
|
||||
"url": "https://github.com/chalk/chalk?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/change-case": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/change-case/-/change-case-3.1.0.tgz",
|
||||
"integrity": "sha512-2AZp7uJZbYEzRPsFoa+ijKdvp9zsrnnt6+yFokfwEpeJm0xuJDVoxiRCAaTzyJND8GJkofo2IcKWaUZ/OECVzw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"camel-case": "^3.0.0",
|
||||
"constant-case": "^2.0.0",
|
||||
"dot-case": "^2.1.0",
|
||||
"header-case": "^1.0.0",
|
||||
"is-lower-case": "^1.1.0",
|
||||
"is-upper-case": "^1.1.0",
|
||||
"lower-case": "^1.1.1",
|
||||
"lower-case-first": "^1.0.0",
|
||||
"no-case": "^2.3.2",
|
||||
"param-case": "^2.1.0",
|
||||
"pascal-case": "^2.0.0",
|
||||
"path-case": "^2.1.0",
|
||||
"sentence-case": "^2.1.0",
|
||||
"snake-case": "^2.1.0",
|
||||
"swap-case": "^1.1.0",
|
||||
"title-case": "^2.1.0",
|
||||
"upper-case": "^1.1.1",
|
||||
"upper-case-first": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/char-regex": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz",
|
||||
@@ -1817,6 +1855,16 @@
|
||||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
|
||||
},
|
||||
"node_modules/constant-case": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/constant-case/-/constant-case-2.0.0.tgz",
|
||||
"integrity": "sha512-eS0N9WwmjTqrOmR3o83F5vW8Z+9R1HnVz3xmzT2PMFug9ly+Au/fxRWlEBSb6LcZwspSsEn9Xs1uw9YgzAg1EQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"snake-case": "^2.1.0",
|
||||
"upper-case": "^1.1.1"
|
||||
}
|
||||
},
|
||||
"node_modules/convert-source-map": {
|
||||
"version": "1.9.0",
|
||||
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz",
|
||||
@@ -1859,12 +1907,27 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/decamelize": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
|
||||
"integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/dedent": {
|
||||
"version": "0.7.0",
|
||||
"resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz",
|
||||
"integrity": "sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/dedent-js": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/dedent-js/-/dedent-js-1.0.1.tgz",
|
||||
"integrity": "sha512-OUepMozQULMLUmhxS95Vudo0jb0UchLimi3+pQ2plj61Fcy8axbP9hbiD4Sz6DPqn6XG3kfmziVfQ1rSys5AJQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/deepmerge": {
|
||||
"version": "4.3.1",
|
||||
"resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz",
|
||||
@@ -1910,6 +1973,15 @@
|
||||
"node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/dot-case": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/dot-case/-/dot-case-2.1.1.tgz",
|
||||
"integrity": "sha512-HnM6ZlFqcajLsyudHq7LeeLDr2rFAVYtDv/hV5qchQEidSck8j9OPUsXY9KwJv/lHMtYlX4DjRQqwFYa+0r8Ug==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"no-case": "^2.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/dunder-proto": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
|
||||
@@ -1959,8 +2031,7 @@
|
||||
"node_modules/emoji-regex": {
|
||||
"version": "8.0.0",
|
||||
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
|
||||
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
|
||||
"dev": true
|
||||
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
|
||||
},
|
||||
"node_modules/error-ex": {
|
||||
"version": "1.3.2",
|
||||
@@ -2227,7 +2298,6 @@
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
|
||||
"integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"locate-path": "^5.0.0",
|
||||
"path-exists": "^4.0.0"
|
||||
@@ -2313,7 +2383,6 @@
|
||||
"version": "2.0.5",
|
||||
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
|
||||
"integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": "6.* || 8.* || >= 10.*"
|
||||
}
|
||||
@@ -2482,6 +2551,22 @@
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/header-case": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/header-case/-/header-case-1.0.1.tgz",
|
||||
"integrity": "sha512-i0q9mkOeSuhXw6bGgiQCCBgY/jlZuV/7dZXyZ9c6LcBrqwvT8eT719E9uxE5LiZftdl+z81Ugbg/VvXV4OJOeQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"no-case": "^2.2.0",
|
||||
"upper-case": "^1.1.3"
|
||||
}
|
||||
},
|
||||
"node_modules/html-entities": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.4.0.tgz",
|
||||
"integrity": "sha512-8nxjcBcd8wovbeKx7h3wTji4e6+rhaVuPNpMqwWgnHh+N9ToqsCs6XztWRBPQ+UtzsoMAdKZtUENoVzU/EMtZA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/html-escaper": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz",
|
||||
@@ -2573,6 +2658,15 @@
|
||||
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/ip-address": {
|
||||
"version": "10.1.0",
|
||||
"resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.1.0.tgz",
|
||||
"integrity": "sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 12"
|
||||
}
|
||||
},
|
||||
"node_modules/is-arrayish": {
|
||||
"version": "0.2.1",
|
||||
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
|
||||
@@ -2616,7 +2710,6 @@
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
|
||||
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
@@ -2642,6 +2735,15 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/is-lower-case": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/is-lower-case/-/is-lower-case-1.1.3.tgz",
|
||||
"integrity": "sha512-+5A1e/WJpLLXZEDlgz4G//WYSHyQBD32qa4Jd3Lw06qQlv3fJHnp3YIHjTQSGzHMgzmVKz2ZP3rBxTHkPw/lxA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"lower-case": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/is-number": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
|
||||
@@ -2664,6 +2766,15 @@
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/is-upper-case": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/is-upper-case/-/is-upper-case-1.1.2.tgz",
|
||||
"integrity": "sha512-GQYSJMgfeAmVwh9ixyk888l7OIhNAGKtY6QA+IrWlu9MDTCaXmeozOZ2S9Knj7bQwBO/H6J2kb+pbyTUiMNbsw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"upper-case": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/isexe": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
|
||||
@@ -2758,6 +2869,7 @@
|
||||
"resolved": "https://registry.npmjs.org/jest/-/jest-28.1.3.tgz",
|
||||
"integrity": "sha512-N4GT5on8UkZgH0O5LUavMRV1EDEhNTL0KEfRmDIeZHSV7p2XgLoY9t9VDUgL6o+yfdgYHVxuz81G8oB9VG5uyA==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@jest/core": "^28.1.3",
|
||||
"@jest/types": "^28.1.3",
|
||||
@@ -3747,7 +3859,6 @@
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
|
||||
"integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"p-locate": "^4.1.0"
|
||||
},
|
||||
@@ -3761,6 +3872,21 @@
|
||||
"integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/lower-case": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz",
|
||||
"integrity": "sha512-2Fgx1Ycm599x+WGpIYwJOvsjmXFzTSc34IwDWALRA/8AopUKAVPwfJ+h5+f85BCp0PWmmJcWzEpxOpoXycMpdA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/lower-case-first": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/lower-case-first/-/lower-case-first-1.0.2.tgz",
|
||||
"integrity": "sha512-UuxaYakO7XeONbKrZf5FEgkantPf5DUqDayzP5VXZrtRPdH86s4kN47I8B3TW10S4QKiE3ziHNf3kRN//okHjA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"lower-case": "^1.1.2"
|
||||
}
|
||||
},
|
||||
"node_modules/lru-cache": {
|
||||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
|
||||
@@ -3923,6 +4049,15 @@
|
||||
"smart-buffer": "^4.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/no-case": {
|
||||
"version": "2.3.2",
|
||||
"resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.2.tgz",
|
||||
"integrity": "sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"lower-case": "^1.1.1"
|
||||
}
|
||||
},
|
||||
"node_modules/node-int64": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz",
|
||||
@@ -4081,7 +4216,6 @@
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
|
||||
"integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"p-limit": "^2.2.0"
|
||||
},
|
||||
@@ -4093,7 +4227,6 @@
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
|
||||
"integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"p-try": "^2.0.0"
|
||||
},
|
||||
@@ -4108,11 +4241,19 @@
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
|
||||
"integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/param-case": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/param-case/-/param-case-2.1.1.tgz",
|
||||
"integrity": "sha512-eQE845L6ot89sk2N8liD8HAuH4ca6Vvr7VWAWwt7+kvvG5aBcPmmphQ68JsEG2qa9n1TykS2DLeMt363AAH8/w==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"no-case": "^2.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/parse-json": {
|
||||
"version": "5.2.0",
|
||||
"resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz",
|
||||
@@ -4131,11 +4272,29 @@
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/pascal-case": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-2.0.1.tgz",
|
||||
"integrity": "sha512-qjS4s8rBOJa2Xm0jmxXiyh1+OFf6ekCWOvUaRgAQSktzlTbMotS0nmG9gyYAybCWBcuP4fsBeRCKNwGBnMe2OQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"camel-case": "^3.0.0",
|
||||
"upper-case-first": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/path-case": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/path-case/-/path-case-2.1.1.tgz",
|
||||
"integrity": "sha512-Ou0N05MioItesaLr9q8TtHVWmJ6fxWdqKB2RohFmNWVyJ+2zeKIeDNWAN6B/Pe7wpzWChhZX6nONYmOnMeJQ/Q==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"no-case": "^2.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/path-exists": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
|
||||
"integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
@@ -4328,11 +4487,16 @@
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
|
||||
"integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/require-main-filename": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz",
|
||||
"integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/resolve": {
|
||||
"version": "1.22.8",
|
||||
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz",
|
||||
@@ -4404,6 +4568,22 @@
|
||||
"semver": "bin/semver.js"
|
||||
}
|
||||
},
|
||||
"node_modules/sentence-case": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/sentence-case/-/sentence-case-2.1.1.tgz",
|
||||
"integrity": "sha512-ENl7cYHaK/Ktwk5OTD+aDbQ3uC8IByu/6Bkg+HDv8Mm+XnBnppVNalcfJTNsp1ibstKh030/JKQQWglDvtKwEQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"no-case": "^2.2.0",
|
||||
"upper-case-first": "^1.1.2"
|
||||
}
|
||||
},
|
||||
"node_modules/set-blocking": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
|
||||
"integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/shebang-command": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
|
||||
@@ -4477,6 +4657,29 @@
|
||||
"npm": ">= 3.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/snake-case": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/snake-case/-/snake-case-2.1.0.tgz",
|
||||
"integrity": "sha512-FMR5YoPFwOLuh4rRz92dywJjyKYZNLpMn1R5ujVpIYkbA9p01fq8RMg0FkO4M+Yobt4MjHeLTJVm5xFFBHSV2Q==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"no-case": "^2.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/socks": {
|
||||
"version": "2.8.7",
|
||||
"resolved": "https://registry.npmjs.org/socks/-/socks-2.8.7.tgz",
|
||||
"integrity": "sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ip-address": "^10.0.1",
|
||||
"smart-buffer": "^4.2.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 10.0.0",
|
||||
"npm": ">= 3.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/source-map": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
||||
@@ -4531,7 +4734,6 @@
|
||||
"version": "4.2.3",
|
||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
|
||||
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"emoji-regex": "^8.0.0",
|
||||
"is-fullwidth-code-point": "^3.0.0",
|
||||
@@ -4545,7 +4747,6 @@
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
|
||||
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"ansi-regex": "^5.0.1"
|
||||
},
|
||||
@@ -4619,6 +4820,16 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/swap-case": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/swap-case/-/swap-case-1.1.2.tgz",
|
||||
"integrity": "sha512-BAmWG6/bx8syfc6qXPprof3Mn5vQgf5dwdUNJhsNqU9WdPt5P+ES/wQ5bxfijy8zwZgZZHslC3iAsxsuQMCzJQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"lower-case": "^1.1.1",
|
||||
"upper-case": "^1.1.1"
|
||||
}
|
||||
},
|
||||
"node_modules/terminal-link": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.1.1.tgz",
|
||||
@@ -4649,6 +4860,16 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/title-case": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/title-case/-/title-case-2.1.1.tgz",
|
||||
"integrity": "sha512-EkJoZ2O3zdCz3zJsYCsxyq2OC5hrxR9mfdd5I+w8h/tmFfeOxJ+vvkxsKxdmN0WtS9zLdHEgfgVOiMVgv+Po4Q==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"no-case": "^2.2.0",
|
||||
"upper-case": "^1.0.3"
|
||||
}
|
||||
},
|
||||
"node_modules/tmpl": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz",
|
||||
@@ -4760,6 +4981,7 @@
|
||||
"version": "10.9.2",
|
||||
"resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz",
|
||||
"integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@cspotcode/source-map-support": "^0.8.0",
|
||||
"@tsconfig/node10": "^1.0.7",
|
||||
@@ -4838,6 +5060,12 @@
|
||||
"integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/underscore": {
|
||||
"version": "1.13.7",
|
||||
"resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.7.tgz",
|
||||
"integrity": "sha512-GMXzWtsc57XAtguZgaQViUOzs0KTkk8ojr3/xAxXLITqf/3EMwxC0inyETfDFjH/Krbhuep0HNbbjI9i/q3F3g==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/undici-types": {
|
||||
"version": "7.16.0",
|
||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz",
|
||||
@@ -4875,6 +5103,21 @@
|
||||
"browserslist": ">= 4.21.0"
|
||||
}
|
||||
},
|
||||
"node_modules/upper-case": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/upper-case/-/upper-case-1.1.3.tgz",
|
||||
"integrity": "sha512-WRbjgmYzgXkCV7zNVpy5YgrHgbBv126rMALQQMrmzOVC4GM2waQ9x7xtm8VU+1yF2kWyPzI9zbZ48n4vSxwfSA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/upper-case-first": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/upper-case-first/-/upper-case-first-1.1.2.tgz",
|
||||
"integrity": "sha512-wINKYvI3Db8dtjikdAqoBbZoP6Q+PZUyfMR7pmwHzjC2quzSkUq5DmPrTtPEqHaz8AGtmsB4TqwapMTM1QAQOQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"upper-case": "^1.1.1"
|
||||
}
|
||||
},
|
||||
"node_modules/v8-compile-cache-lib": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz",
|
||||
@@ -4924,6 +5167,104 @@
|
||||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/which-module": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz",
|
||||
"integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/whois": {
|
||||
"version": "2.16.1",
|
||||
"resolved": "https://registry.npmjs.org/whois/-/whois-2.16.1.tgz",
|
||||
"integrity": "sha512-gCxr+knAuXzsHJlHaIi8bCZoRU9anysyKbo0mgjAkkanNdOvUhBZShgG/ckcpKryDUVs2cH684MU+wOLjBYlAA==",
|
||||
"license": "FreeBSD",
|
||||
"dependencies": {
|
||||
"socks": "^2.2.2",
|
||||
"underscore": "^1.9.1",
|
||||
"yargs": "^15.4.1"
|
||||
},
|
||||
"bin": {
|
||||
"whois": "bin.js"
|
||||
}
|
||||
},
|
||||
"node_modules/whois-json": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/whois-json/-/whois-json-2.0.4.tgz",
|
||||
"integrity": "sha512-ui9Qe0qS4yWtFAPw0q+QPuuH+m4vDDtoO/YtqmF00YoPMMNplhya7SqTVAxThWIVXhWHPEKajFEulegmysdlwQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"change-case": "^3.0.2",
|
||||
"dedent-js": "^1.0.1",
|
||||
"html-entities": "^1.2.1",
|
||||
"whois": "^2.6.0"
|
||||
}
|
||||
},
|
||||
"node_modules/whois/node_modules/cliui": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz",
|
||||
"integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"string-width": "^4.2.0",
|
||||
"strip-ansi": "^6.0.0",
|
||||
"wrap-ansi": "^6.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/whois/node_modules/wrap-ansi": {
|
||||
"version": "6.2.0",
|
||||
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
|
||||
"integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ansi-styles": "^4.0.0",
|
||||
"string-width": "^4.1.0",
|
||||
"strip-ansi": "^6.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/whois/node_modules/y18n": {
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz",
|
||||
"integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/whois/node_modules/yargs": {
|
||||
"version": "15.4.1",
|
||||
"resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz",
|
||||
"integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"cliui": "^6.0.0",
|
||||
"decamelize": "^1.2.0",
|
||||
"find-up": "^4.1.0",
|
||||
"get-caller-file": "^2.0.1",
|
||||
"require-directory": "^2.1.1",
|
||||
"require-main-filename": "^2.0.0",
|
||||
"set-blocking": "^2.0.0",
|
||||
"string-width": "^4.2.0",
|
||||
"which-module": "^2.0.0",
|
||||
"y18n": "^4.0.0",
|
||||
"yargs-parser": "^18.1.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/whois/node_modules/yargs-parser": {
|
||||
"version": "18.1.3",
|
||||
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz",
|
||||
"integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"camelcase": "^5.0.0",
|
||||
"decamelize": "^1.2.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/wrap-ansi": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
|
||||
|
||||
@@ -30,7 +30,8 @@
|
||||
"net-snmp": "^3.26.1",
|
||||
"ping": "^0.4.4",
|
||||
"playwright": "^1.57.0",
|
||||
"ts-node": "^10.9.1"
|
||||
"ts-node": "^10.9.1",
|
||||
"whois-json": "^2.0.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jest": "^27.5.2",
|
||||
|
||||
Reference in New Issue
Block a user