ESLint: Fix more warnings and errors.

This commit is contained in:
baldo 2022-08-23 21:38:37 +02:00
parent 66fb4e5004
commit bfd6ca1d26
9 changed files with 84 additions and 56 deletions

View file

@ -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[] }) => {
.then(
(result: {
total: number;
pageNodes: DomainSpecificNodeResponse[];
}) => {
res.set("X-Total-Count", result.total.toString(10));
return Resources.success(res, result.pageNodes);
})
.catch((err: any) => Resources.error(res, err));
return Resources.success(
res,
result.pageNodes.map(filterUndefinedFromJSON)
);
}
)
.catch((err) => Resources.error(res, err));
}

View file

@ -196,21 +196,23 @@ export async function sendPendingMails(): Promise<void> {
const startTime = moment();
while (true) {
Logger.tag("mail", "queue").debug("Sending next batch...");
const pendingMails = await findPendingMailsBefore(
let pendingMails = await findPendingMailsBefore(
startTime,
MAIL_QUEUE_DB_BATCH_SIZE
);
if (_.isEmpty(pendingMails)) {
Logger.tag("mail", "queue").debug("Done sending pending mails.");
return;
}
while (!_.isEmpty(pendingMails)) {
Logger.tag("mail", "queue").debug("Sending next batch...");
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.");
}

View file

@ -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);
};

View file

@ -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();

View file

@ -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}`
);

View file

@ -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;

View file

@ -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;

View file

@ -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 {

View file

@ -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();