ESLint: Fix more warnings and errors.
This commit is contained in:
parent
66fb4e5004
commit
bfd6ca1d26
9 changed files with 84 additions and 56 deletions
|
@ -10,6 +10,7 @@ import { Request, Response } from "express";
|
|||
import {
|
||||
CreateOrUpdateNode,
|
||||
DomainSpecificNodeResponse,
|
||||
filterUndefinedFromJSON,
|
||||
isCreateOrUpdateNode,
|
||||
isNodeSortField,
|
||||
isString,
|
||||
|
@ -108,7 +109,7 @@ export const get = handleJSONWithData<NodeResponse>(async (data) => {
|
|||
|
||||
async function doGetAll(
|
||||
req: Request
|
||||
): Promise<{ total: number; pageNodes: any }> {
|
||||
): Promise<{ total: number; pageNodes: DomainSpecificNodeResponse[] }> {
|
||||
const restParams = await Resources.getValidRestParams("list", "node", req);
|
||||
|
||||
const nodes = await NodeService.getAllNodes();
|
||||
|
@ -159,9 +160,17 @@ async function doGetAll(
|
|||
|
||||
export function getAll(req: Request, res: Response): void {
|
||||
doGetAll(req)
|
||||
.then((result: { total: number; pageNodes: any[] }) => {
|
||||
res.set("X-Total-Count", result.total.toString(10));
|
||||
return Resources.success(res, result.pageNodes);
|
||||
})
|
||||
.catch((err: any) => Resources.error(res, err));
|
||||
.then(
|
||||
(result: {
|
||||
total: number;
|
||||
pageNodes: DomainSpecificNodeResponse[];
|
||||
}) => {
|
||||
res.set("X-Total-Count", result.total.toString(10));
|
||||
return Resources.success(
|
||||
res,
|
||||
result.pageNodes.map(filterUndefinedFromJSON)
|
||||
);
|
||||
}
|
||||
)
|
||||
.catch((err) => Resources.error(res, err));
|
||||
}
|
||||
|
|
|
@ -196,21 +196,23 @@ export async function sendPendingMails(): Promise<void> {
|
|||
|
||||
const startTime = moment();
|
||||
|
||||
while (true) {
|
||||
let pendingMails = await findPendingMailsBefore(
|
||||
startTime,
|
||||
MAIL_QUEUE_DB_BATCH_SIZE
|
||||
);
|
||||
|
||||
while (!_.isEmpty(pendingMails)) {
|
||||
Logger.tag("mail", "queue").debug("Sending next batch...");
|
||||
|
||||
const pendingMails = await findPendingMailsBefore(
|
||||
startTime,
|
||||
MAIL_QUEUE_DB_BATCH_SIZE
|
||||
);
|
||||
|
||||
if (_.isEmpty(pendingMails)) {
|
||||
Logger.tag("mail", "queue").debug("Done sending pending mails.");
|
||||
return;
|
||||
}
|
||||
|
||||
for (const pendingMail of pendingMails) {
|
||||
await sendPendingMail(pendingMail);
|
||||
}
|
||||
|
||||
pendingMails = await findPendingMailsBefore(
|
||||
startTime,
|
||||
MAIL_QUEUE_DB_BATCH_SIZE
|
||||
);
|
||||
}
|
||||
|
||||
Logger.tag("mail", "queue").debug("Done sending pending mails.");
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ const templateFunctions: {
|
|||
| ((unix: number) => string);
|
||||
} = {};
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
function renderSnippet(this: any, name: string, data: MailData): string {
|
||||
const snippetFile = snippetsBasePath + "/" + name + ".html";
|
||||
|
||||
|
@ -34,7 +35,9 @@ function renderSnippet(this: any, name: string, data: MailData): string {
|
|||
);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
function snippet(name: string): (this: any, data: MailData) => string {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
return function (this: any, data: MailData): string {
|
||||
return renderSnippet.bind(this)(name, data);
|
||||
};
|
||||
|
|
|
@ -25,15 +25,6 @@ beforeEach(() => {
|
|||
mockedLogger.reset();
|
||||
});
|
||||
|
||||
test("parseNode() should fail parsing node for undefined node data", () => {
|
||||
// given
|
||||
const importTimestamp = now();
|
||||
const nodeData = undefined;
|
||||
|
||||
// then
|
||||
expect(() => parseNode(importTimestamp, nodeData)).toThrowError();
|
||||
});
|
||||
|
||||
test("parseNode() should fail parsing node for empty node data", () => {
|
||||
// given
|
||||
const importTimestamp = now();
|
||||
|
|
|
@ -24,9 +24,11 @@ import {
|
|||
isDomain,
|
||||
isMonitoringSortField,
|
||||
isOnlineState,
|
||||
isPlainObject,
|
||||
isSite,
|
||||
isString,
|
||||
isUndefined,
|
||||
JSONValue,
|
||||
MAC,
|
||||
MailType,
|
||||
MonitoringSortField,
|
||||
|
@ -35,6 +37,7 @@ import {
|
|||
NodeId,
|
||||
NodeStateData,
|
||||
OnlineState,
|
||||
parseJSON,
|
||||
RunResult,
|
||||
Site,
|
||||
StoredNode,
|
||||
|
@ -206,13 +209,13 @@ const isValidMac = forConstraint(CONSTRAINTS.node.mac, false);
|
|||
|
||||
export function parseNode(
|
||||
importTimestamp: UnixTimestampSeconds,
|
||||
nodeData: any
|
||||
nodeData: JSONValue
|
||||
): ParsedNode {
|
||||
if (!_.isPlainObject(nodeData)) {
|
||||
if (!isPlainObject(nodeData)) {
|
||||
throw new Error("Unexpected node type: " + typeof nodeData);
|
||||
}
|
||||
|
||||
if (!_.isPlainObject(nodeData.nodeinfo)) {
|
||||
if (!isPlainObject(nodeData.nodeinfo)) {
|
||||
throw new Error(
|
||||
"Unexpected nodeinfo type: " + typeof nodeData.nodeinfo
|
||||
);
|
||||
|
@ -225,7 +228,7 @@ export function parseNode(
|
|||
);
|
||||
}
|
||||
|
||||
if (!_.isPlainObject(nodeData.nodeinfo.network)) {
|
||||
if (!isPlainObject(nodeData.nodeinfo.network)) {
|
||||
throw new Error(
|
||||
"Node " +
|
||||
nodeId +
|
||||
|
@ -239,9 +242,9 @@ export function parseNode(
|
|||
"Node " + nodeId + ": Invalid MAC: " + nodeData.nodeinfo.network.mac
|
||||
);
|
||||
}
|
||||
const mac = normalizeMac(nodeData.nodeinfo.network.mac) as MAC;
|
||||
const mac = normalizeMac(nodeData.nodeinfo.network.mac as MAC);
|
||||
|
||||
if (!_.isPlainObject(nodeData.flags)) {
|
||||
if (!isPlainObject(nodeData.flags)) {
|
||||
throw new Error(
|
||||
"Node " +
|
||||
nodeId +
|
||||
|
@ -271,7 +274,7 @@ export function parseNode(
|
|||
|
||||
let site: Site | undefined;
|
||||
if (
|
||||
_.isPlainObject(nodeData.nodeinfo.system) &&
|
||||
isPlainObject(nodeData.nodeinfo.system) &&
|
||||
isSite(nodeData.nodeinfo.system.site_code)
|
||||
) {
|
||||
site = nodeData.nodeinfo.system.site_code;
|
||||
|
@ -279,7 +282,7 @@ export function parseNode(
|
|||
|
||||
let domain: Domain | undefined;
|
||||
if (
|
||||
_.isPlainObject(nodeData.nodeinfo.system) &&
|
||||
isPlainObject(nodeData.nodeinfo.system) &&
|
||||
isDomain(nodeData.nodeinfo.system.domain_code)
|
||||
) {
|
||||
domain = nodeData.nodeinfo.system.domain_code;
|
||||
|
@ -300,9 +303,9 @@ export function parseNodesJson(body: string): NodesParsingResult {
|
|||
"Parsing nodes.json..."
|
||||
);
|
||||
|
||||
const json = JSON.parse(body);
|
||||
const json = parseJSON(body);
|
||||
|
||||
if (!_.isPlainObject(json)) {
|
||||
if (!isPlainObject(json)) {
|
||||
throw new Error(
|
||||
`Expecting a JSON object as the nodes.json root, but got: ${typeof json}`
|
||||
);
|
||||
|
|
|
@ -405,7 +405,7 @@ function setNodeValue(
|
|||
case LINE_PREFIX.TOKEN:
|
||||
node.token = value as Token;
|
||||
break;
|
||||
case LINE_PREFIX.MONITORING:
|
||||
case LINE_PREFIX.MONITORING: {
|
||||
const active = value === "aktiv";
|
||||
const pending = value === "pending";
|
||||
node.monitoringState = active
|
||||
|
@ -414,6 +414,7 @@ function setNodeValue(
|
|||
? MonitoringState.PENDING
|
||||
: MonitoringState.DISABLED;
|
||||
break;
|
||||
}
|
||||
case LINE_PREFIX.MONITORING_TOKEN:
|
||||
nodeSecrets.monitoringToken = value as MonitoringToken;
|
||||
break;
|
||||
|
|
|
@ -77,6 +77,10 @@ export function isObject(arg: unknown): arg is object {
|
|||
return arg !== null && typeof arg === "object";
|
||||
}
|
||||
|
||||
export function isPlainObject(arg: unknown): arg is { [key: string]: unknown } {
|
||||
return isObject(arg) && !Array.isArray(arg);
|
||||
}
|
||||
|
||||
export function hasOwnProperty<Key extends PropertyKey>(
|
||||
arg: unknown,
|
||||
key: Key
|
||||
|
@ -84,6 +88,13 @@ export function hasOwnProperty<Key extends PropertyKey>(
|
|||
return isObject(arg) && key in arg;
|
||||
}
|
||||
|
||||
export function getFieldIfExists(
|
||||
arg: unknown,
|
||||
key: PropertyKey
|
||||
): unknown | undefined {
|
||||
return hasOwnProperty(arg, key) ? arg[key] : undefined;
|
||||
}
|
||||
|
||||
export function isArray<T>(arg: unknown, isT: TypeGuard<T>): arg is Array<T> {
|
||||
if (!Array.isArray(arg)) {
|
||||
return false;
|
||||
|
|
|
@ -25,6 +25,9 @@ export interface Constraint {
|
|||
}
|
||||
|
||||
export type Constraints = { [key: string]: Constraint };
|
||||
export type NestedConstraints = {
|
||||
[key: string]: Constraint | Constraints | NestedConstraints;
|
||||
};
|
||||
export type Values = { [key: string]: unknown };
|
||||
|
||||
export function isConstraint(arg: unknown): arg is Constraint {
|
||||
|
|
|
@ -7,12 +7,14 @@ import {
|
|||
Constraints,
|
||||
forConstraints,
|
||||
isConstraints,
|
||||
NestedConstraints,
|
||||
} from "../shared/validation/validator";
|
||||
import { Request, Response } from "express";
|
||||
import {
|
||||
EnumTypeGuard,
|
||||
EnumValue,
|
||||
type GenericSortField,
|
||||
getFieldIfExists,
|
||||
isJSONObject,
|
||||
isNumber,
|
||||
isString,
|
||||
|
@ -26,7 +28,7 @@ import {
|
|||
export type RequestData = JSONObject;
|
||||
export type RequestHandler = (request: Request, response: Response) => void;
|
||||
|
||||
export type Entity = { [key: string]: any };
|
||||
export type Entity = { [key: string]: unknown };
|
||||
|
||||
export type RestParams = {
|
||||
q?: string;
|
||||
|
@ -180,7 +182,7 @@ export async function getValidRestParams(
|
|||
subtype: string | null,
|
||||
req: Request
|
||||
): Promise<RestParams> {
|
||||
const restConstraints = CONSTRAINTS.rest as { [key: string]: any };
|
||||
const restConstraints = CONSTRAINTS.rest as { [key: string]: Constraints };
|
||||
if (!(type in restConstraints) || !isConstraints(restConstraints[type])) {
|
||||
Logger.tag("validation", "rest").error(
|
||||
"Unknown REST resource type: {}",
|
||||
|
@ -193,18 +195,16 @@ export async function getValidRestParams(
|
|||
let filterConstraints: Constraints = {};
|
||||
if (subtype) {
|
||||
const subtypeFilters = subtype + "Filters";
|
||||
const constraintsObj = CONSTRAINTS as { [key: string]: any };
|
||||
if (
|
||||
!(subtypeFilters in constraintsObj) ||
|
||||
!isConstraints(constraintsObj[subtypeFilters])
|
||||
) {
|
||||
const nestedConstraints = CONSTRAINTS as NestedConstraints;
|
||||
const subConstraints = nestedConstraints[subtypeFilters];
|
||||
if (!isConstraints(subConstraints)) {
|
||||
Logger.tag("validation", "rest").error(
|
||||
"Unknown REST resource subtype: {}",
|
||||
subtype
|
||||
);
|
||||
throw { data: "Internal error.", type: ErrorTypes.internalError };
|
||||
}
|
||||
filterConstraints = constraintsObj[subtypeFilters];
|
||||
filterConstraints = subConstraints;
|
||||
}
|
||||
|
||||
const data = getData(req);
|
||||
|
@ -232,7 +232,7 @@ export function filter<E>(
|
|||
query = query.trim().toLowerCase();
|
||||
}
|
||||
|
||||
function queryMatches(entity: Entity): boolean {
|
||||
function queryMatches(entity: E): boolean {
|
||||
if (!query) {
|
||||
return true;
|
||||
}
|
||||
|
@ -240,7 +240,7 @@ export function filter<E>(
|
|||
if (!query) {
|
||||
return true;
|
||||
}
|
||||
let value = entity[field];
|
||||
let value = getFieldIfExists(entity, field);
|
||||
if (isNumber(value)) {
|
||||
value = value.toString();
|
||||
}
|
||||
|
@ -249,21 +249,21 @@ export function filter<E>(
|
|||
return false;
|
||||
}
|
||||
|
||||
value = value.toLowerCase();
|
||||
const lowerCaseValue = value.toLowerCase();
|
||||
if (field === "mac") {
|
||||
return _.includes(
|
||||
value.replace(/:/g, ""),
|
||||
lowerCaseValue.replace(/:/g, ""),
|
||||
query.replace(/:/g, "")
|
||||
);
|
||||
}
|
||||
|
||||
return _.includes(value, query);
|
||||
return _.includes(lowerCaseValue, query);
|
||||
});
|
||||
}
|
||||
|
||||
const filters = restParams.filters;
|
||||
|
||||
function filtersMatch(entity: Entity): boolean {
|
||||
function filtersMatch(entity: E): boolean {
|
||||
if (isUndefined(filters) || _.isEmpty(filters)) {
|
||||
return true;
|
||||
}
|
||||
|
@ -275,9 +275,13 @@ export function filter<E>(
|
|||
if (key.startsWith("has")) {
|
||||
const entityKey =
|
||||
key.substring(3, 4).toLowerCase() + key.substring(4);
|
||||
return _.isEmpty(entity[entityKey]).toString() !== value;
|
||||
return (
|
||||
_.isEmpty(
|
||||
getFieldIfExists(entity, entityKey)
|
||||
).toString() !== value
|
||||
);
|
||||
}
|
||||
return entity[key] === value;
|
||||
return getFieldIfExists(entity, key) === value;
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -287,7 +291,8 @@ export function filter<E>(
|
|||
}
|
||||
|
||||
export function sort<
|
||||
Type extends { [Key in SortField]: unknown },
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
Type extends { [Key in SortField]: any },
|
||||
SortField extends string
|
||||
>(
|
||||
entities: Type[],
|
||||
|
@ -303,8 +308,8 @@ export function sort<
|
|||
|
||||
const sorted = entities.slice(0);
|
||||
sorted.sort((a, b) => {
|
||||
let as: any = a[sortField];
|
||||
let bs: any = b[sortField];
|
||||
let as = a[sortField];
|
||||
let bs = b[sortField];
|
||||
|
||||
if (isString(as)) {
|
||||
as = as.toLowerCase();
|
||||
|
|
Loading…
Reference in a new issue