ESLint: Auto reformat and fixing some warnings / errors.
This commit is contained in:
parent
5237db38e0
commit
91690509d3
50 changed files with 2141 additions and 1493 deletions
server/utils
|
@ -1,10 +1,14 @@
|
|||
import _ from "lodash";
|
||||
|
||||
import CONSTRAINTS from "../shared/validation/constraints";
|
||||
import ErrorTypes from "../utils/errorTypes";
|
||||
import ErrorTypes from "./errorTypes";
|
||||
import Logger from "../logger";
|
||||
import {Constraints, forConstraints, isConstraints} from "../shared/validation/validator";
|
||||
import {Request, Response} from "express";
|
||||
import {
|
||||
Constraints,
|
||||
forConstraints,
|
||||
isConstraints,
|
||||
} from "../shared/validation/validator";
|
||||
import { Request, Response } from "express";
|
||||
import {
|
||||
EnumTypeGuard,
|
||||
EnumValue,
|
||||
|
@ -16,7 +20,7 @@ import {
|
|||
JSONObject,
|
||||
JSONValue,
|
||||
SortDirection,
|
||||
TypeGuard
|
||||
TypeGuard,
|
||||
} from "../types";
|
||||
|
||||
export type RequestData = JSONObject;
|
||||
|
@ -36,21 +40,36 @@ export type RestParams = {
|
|||
filters?: FilterClause;
|
||||
};
|
||||
|
||||
export type OrderByClause = { query: string, params: any[] };
|
||||
export type LimitOffsetClause = { query: string, params: any[] };
|
||||
export type FilterClause = { query: string, params: any[] };
|
||||
export type OrderByClause = { query: string; params: unknown[] };
|
||||
export type LimitOffsetClause = { query: string; params: unknown[] };
|
||||
export type FilterClause = { query: string; params: unknown[] };
|
||||
|
||||
function respond(res: Response, httpCode: number, data: string, type: "html"): void;
|
||||
function respond(res: Response, httpCode: number, data: JSONValue, type: "json"): void;
|
||||
function respond(res: Response, httpCode: number, data: JSONValue, type: "html" | "json"): void {
|
||||
function respond(
|
||||
res: Response,
|
||||
httpCode: number,
|
||||
data: string,
|
||||
type: "html"
|
||||
): void;
|
||||
function respond(
|
||||
res: Response,
|
||||
httpCode: number,
|
||||
data: JSONValue,
|
||||
type: "json"
|
||||
): void;
|
||||
function respond(
|
||||
res: Response,
|
||||
httpCode: number,
|
||||
data: JSONValue,
|
||||
type: "html" | "json"
|
||||
): void {
|
||||
switch (type) {
|
||||
case 'html':
|
||||
res.writeHead(httpCode, {'Content-Type': 'text/html'});
|
||||
case "html":
|
||||
res.writeHead(httpCode, { "Content-Type": "text/html" });
|
||||
res.end(data);
|
||||
break;
|
||||
|
||||
default:
|
||||
res.writeHead(httpCode, {'Content-Type': 'application/json'});
|
||||
res.writeHead(httpCode, { "Content-Type": "application/json" });
|
||||
res.end(JSON.stringify(data));
|
||||
break;
|
||||
}
|
||||
|
@ -59,16 +78,22 @@ function respond(res: Response, httpCode: number, data: JSONValue, type: "html"
|
|||
function orderByClause<S>(
|
||||
restParams: RestParams,
|
||||
defaultSortField: EnumValue<S>,
|
||||
isSortField: EnumTypeGuard<S>,
|
||||
isSortField: EnumTypeGuard<S>
|
||||
): OrderByClause {
|
||||
let sortField: EnumValue<S> | undefined = isSortField(restParams._sortField) ? restParams._sortField : undefined;
|
||||
let sortField: EnumValue<S> | undefined = isSortField(restParams._sortField)
|
||||
? restParams._sortField
|
||||
: undefined;
|
||||
if (!sortField) {
|
||||
sortField = defaultSortField;
|
||||
}
|
||||
|
||||
return {
|
||||
query: 'ORDER BY LOWER(' + sortField + ') ' + (restParams._sortDir === SortDirection.ASCENDING ? 'ASC' : 'DESC'),
|
||||
params: []
|
||||
query:
|
||||
"ORDER BY LOWER(" +
|
||||
sortField +
|
||||
") " +
|
||||
(restParams._sortDir === SortDirection.ASCENDING ? "ASC" : "DESC"),
|
||||
params: [],
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -77,55 +102,64 @@ function limitOffsetClause(restParams: RestParams): LimitOffsetClause {
|
|||
const perPage = restParams._perPage;
|
||||
|
||||
return {
|
||||
query: 'LIMIT ? OFFSET ?',
|
||||
params: [perPage, ((page - 1) * perPage)]
|
||||
query: "LIMIT ? OFFSET ?",
|
||||
params: [perPage, (page - 1) * perPage],
|
||||
};
|
||||
}
|
||||
|
||||
function escapeForLikePattern(str: string): string {
|
||||
return str
|
||||
.replace(/\\/g, '\\\\')
|
||||
.replace(/%/g, '\\%')
|
||||
.replace(/_/g, '\\_');
|
||||
return str.replace(/\\/g, "\\\\").replace(/%/g, "\\%").replace(/_/g, "\\_");
|
||||
}
|
||||
|
||||
function filterCondition(restParams: RestParams, filterFields: string[]): FilterClause {
|
||||
function filterCondition(
|
||||
restParams: RestParams,
|
||||
filterFields: string[]
|
||||
): FilterClause {
|
||||
if (_.isEmpty(filterFields)) {
|
||||
return {
|
||||
query: '1 = 1',
|
||||
params: []
|
||||
query: "1 = 1",
|
||||
params: [],
|
||||
};
|
||||
}
|
||||
|
||||
let query = filterFields
|
||||
.map(field => 'LOWER(' + field + ') LIKE ?')
|
||||
.join(' OR ');
|
||||
.map((field) => "LOWER(" + field + ") LIKE ?")
|
||||
.join(" OR ");
|
||||
|
||||
query += ' ESCAPE \'\\\'';
|
||||
query += " ESCAPE '\\'";
|
||||
|
||||
const search = '%' + (isString(restParams.q) ? escapeForLikePattern(restParams.q.trim().toLowerCase()) : '') + '%';
|
||||
const search =
|
||||
"%" +
|
||||
(isString(restParams.q)
|
||||
? escapeForLikePattern(restParams.q.trim().toLowerCase())
|
||||
: "") +
|
||||
"%";
|
||||
const params = _.times(filterFields.length, () => search);
|
||||
|
||||
return {
|
||||
query: query,
|
||||
params: params
|
||||
params: params,
|
||||
};
|
||||
}
|
||||
|
||||
function getConstrainedValues(data: { [key: string]: any }, constraints: Constraints): { [key: string]: any } {
|
||||
const values: { [key: string]: any } = {};
|
||||
function getConstrainedValues(
|
||||
data: { [key: string]: unknown },
|
||||
constraints: Constraints
|
||||
): { [key: string]: unknown } {
|
||||
const values: { [key: string]: unknown } = {};
|
||||
for (const key of Object.keys(constraints)) {
|
||||
const value = data[key];
|
||||
values[key] =
|
||||
isUndefined(value) && key in constraints && !isUndefined(constraints[key].default)
|
||||
isUndefined(value) &&
|
||||
key in constraints &&
|
||||
!isUndefined(constraints[key].default)
|
||||
? constraints[key].default
|
||||
: value;
|
||||
|
||||
}
|
||||
return values;
|
||||
}
|
||||
|
||||
function normalize(data: any): JSONObject {
|
||||
function normalize(data: unknown): JSONObject {
|
||||
return isJSONObject(data) ? data : {};
|
||||
}
|
||||
|
||||
|
@ -144,23 +178,31 @@ export function getData(req: Request): RequestData {
|
|||
export async function getValidRestParams(
|
||||
type: string,
|
||||
subtype: string | null,
|
||||
req: Request,
|
||||
req: Request
|
||||
): Promise<RestParams> {
|
||||
const restConstraints = CONSTRAINTS.rest as { [key: string]: any };
|
||||
let constraints: Constraints;
|
||||
if (!(type in restConstraints) || !isConstraints(restConstraints[type])) {
|
||||
Logger.tag('validation', 'rest').error('Unknown REST resource type: {}', type);
|
||||
throw {data: 'Internal error.', type: ErrorTypes.internalError};
|
||||
Logger.tag("validation", "rest").error(
|
||||
"Unknown REST resource type: {}",
|
||||
type
|
||||
);
|
||||
throw { data: "Internal error.", type: ErrorTypes.internalError };
|
||||
}
|
||||
constraints = restConstraints[type];
|
||||
const constraints: Constraints = restConstraints[type];
|
||||
|
||||
let filterConstraints: Constraints = {};
|
||||
if (subtype) {
|
||||
const subtypeFilters = subtype + 'Filters';
|
||||
const subtypeFilters = subtype + "Filters";
|
||||
const constraintsObj = CONSTRAINTS as { [key: string]: any };
|
||||
if (!(subtypeFilters in constraintsObj) || !isConstraints(constraintsObj[subtypeFilters])) {
|
||||
Logger.tag('validation', 'rest').error('Unknown REST resource subtype: {}', subtype);
|
||||
throw {data: 'Internal error.', type: ErrorTypes.internalError};
|
||||
if (
|
||||
!(subtypeFilters in constraintsObj) ||
|
||||
!isConstraints(constraintsObj[subtypeFilters])
|
||||
) {
|
||||
Logger.tag("validation", "rest").error(
|
||||
"Unknown REST resource subtype: {}",
|
||||
subtype
|
||||
);
|
||||
throw { data: "Internal error.", type: ErrorTypes.internalError };
|
||||
}
|
||||
filterConstraints = constraintsObj[subtypeFilters];
|
||||
}
|
||||
|
@ -173,14 +215,18 @@ export async function getValidRestParams(
|
|||
const areValidParams = forConstraints(constraints, false);
|
||||
const areValidFilters = forConstraints(filterConstraints, false);
|
||||
if (!areValidParams(restParams) || !areValidFilters(filterParams)) {
|
||||
throw {data: 'Invalid REST parameters.', type: ErrorTypes.badRequest};
|
||||
throw { data: "Invalid REST parameters.", type: ErrorTypes.badRequest };
|
||||
}
|
||||
|
||||
restParams.filters = filterParams;
|
||||
return restParams as RestParams;
|
||||
}
|
||||
|
||||
export function filter<E>(entities: E[], allowedFilterFields: string[], restParams: RestParams): E[] {
|
||||
export function filter<E>(
|
||||
entities: E[],
|
||||
allowedFilterFields: string[],
|
||||
restParams: RestParams
|
||||
): E[] {
|
||||
let query = restParams.q;
|
||||
if (query) {
|
||||
query = query.trim().toLowerCase();
|
||||
|
@ -204,8 +250,11 @@ export function filter<E>(entities: E[], allowedFilterFields: string[], restPara
|
|||
}
|
||||
|
||||
value = value.toLowerCase();
|
||||
if (field === 'mac') {
|
||||
return _.includes(value.replace(/:/g, ''), query.replace(/:/g, ''));
|
||||
if (field === "mac") {
|
||||
return _.includes(
|
||||
value.replace(/:/g, ""),
|
||||
query.replace(/:/g, "")
|
||||
);
|
||||
}
|
||||
|
||||
return _.includes(value, query);
|
||||
|
@ -223,27 +272,36 @@ export function filter<E>(entities: E[], allowedFilterFields: string[], restPara
|
|||
if (isUndefined(value)) {
|
||||
return true;
|
||||
}
|
||||
if (key.startsWith('has')) {
|
||||
const entityKey = key.substring(3, 4).toLowerCase() + key.substring(4);
|
||||
if (key.startsWith("has")) {
|
||||
const entityKey =
|
||||
key.substring(3, 4).toLowerCase() + key.substring(4);
|
||||
return _.isEmpty(entity[entityKey]).toString() !== value;
|
||||
}
|
||||
return entity[key] === value;
|
||||
});
|
||||
}
|
||||
|
||||
return entities.filter(entity => queryMatches(entity) && filtersMatch(entity));
|
||||
return entities.filter(
|
||||
(entity) => queryMatches(entity) && filtersMatch(entity)
|
||||
);
|
||||
}
|
||||
|
||||
export function sort<T extends Record<S, any>, S extends string>(entities: T[], isSortField: TypeGuard<S>, restParams: RestParams): T[] {
|
||||
const sortField: S | undefined = isSortField(restParams._sortField) ? restParams._sortField : undefined;
|
||||
export function sort<T extends Record<S, unknown>, S extends string>(
|
||||
entities: T[],
|
||||
isSortField: TypeGuard<S>,
|
||||
restParams: RestParams
|
||||
): T[] {
|
||||
const sortField: S | undefined = isSortField(restParams._sortField)
|
||||
? restParams._sortField
|
||||
: undefined;
|
||||
if (!sortField) {
|
||||
return entities;
|
||||
}
|
||||
|
||||
const sorted = entities.slice(0);
|
||||
sorted.sort((a, b) => {
|
||||
let as = a[sortField];
|
||||
let bs = b[sortField];
|
||||
let as: any = a[sortField];
|
||||
let bs: any = b[sortField];
|
||||
|
||||
if (isString(as)) {
|
||||
as = as.toLowerCase();
|
||||
|
@ -259,69 +317,74 @@ export function sort<T extends Record<S, any>, S extends string>(entities: T[],
|
|||
order = 1;
|
||||
}
|
||||
|
||||
return restParams._sortDir === SortDirection.DESCENDING ? -order : order;
|
||||
return restParams._sortDir === SortDirection.DESCENDING
|
||||
? -order
|
||||
: order;
|
||||
});
|
||||
|
||||
return sorted;
|
||||
}
|
||||
|
||||
export function getPageEntities<Entity>(entities: Entity[], restParams: RestParams): Entity[] {
|
||||
export function getPageEntities<Entity>(
|
||||
entities: Entity[],
|
||||
restParams: RestParams
|
||||
): Entity[] {
|
||||
const page = restParams._page;
|
||||
const perPage = restParams._perPage;
|
||||
|
||||
return entities.slice((page - 1) * perPage, page * perPage);
|
||||
}
|
||||
|
||||
export {filterCondition as whereCondition};
|
||||
export { filterCondition as whereCondition };
|
||||
|
||||
export function filterClause<S>(
|
||||
restParams: RestParams,
|
||||
defaultSortField: EnumValue<S>,
|
||||
isSortField: EnumTypeGuard<S>,
|
||||
filterFields: string[],
|
||||
filterFields: string[]
|
||||
): FilterClause {
|
||||
const orderBy = orderByClause<S>(
|
||||
restParams,
|
||||
defaultSortField,
|
||||
isSortField,
|
||||
);
|
||||
const orderBy = orderByClause<S>(restParams, defaultSortField, isSortField);
|
||||
const limitOffset = limitOffsetClause(restParams);
|
||||
|
||||
const filter = filterCondition(
|
||||
restParams,
|
||||
filterFields
|
||||
);
|
||||
const filter = filterCondition(restParams, filterFields);
|
||||
|
||||
return {
|
||||
query: filter.query + ' ' + orderBy.query + ' ' + limitOffset.query,
|
||||
params: [...filter.params, ...orderBy.params, ...limitOffset.params]
|
||||
query: filter.query + " " + orderBy.query + " " + limitOffset.query,
|
||||
params: [...filter.params, ...orderBy.params, ...limitOffset.params],
|
||||
};
|
||||
}
|
||||
|
||||
export function success(res: Response, data: JSONValue) {
|
||||
respond(res, 200, data, 'json');
|
||||
respond(res, 200, data, "json");
|
||||
}
|
||||
|
||||
export function successHtml(res: Response, html: string) {
|
||||
respond(res, 200, html, 'html');
|
||||
respond(res, 200, html, "html");
|
||||
}
|
||||
|
||||
export function error(res: Response, err: { data: JSONValue, type: { code: number } }) {
|
||||
respond(res, err.type.code, err.data, 'json');
|
||||
export function error(
|
||||
res: Response,
|
||||
err: { data: JSONValue; type: { code: number } }
|
||||
) {
|
||||
respond(res, err.type.code, err.data, "json");
|
||||
}
|
||||
|
||||
export function handleJSON<Response>(handler: () => Promise<Response>): RequestHandler {
|
||||
export function handleJSON<Response>(
|
||||
handler: () => Promise<Response>
|
||||
): RequestHandler {
|
||||
return (request, response) => {
|
||||
handler()
|
||||
.then(data => success(response, data || {}))
|
||||
.catch(e => error(response, e));
|
||||
.then((data) => success(response, data || {}))
|
||||
.catch((e) => error(response, e));
|
||||
};
|
||||
}
|
||||
|
||||
export function handleJSONWithData<Response>(handler: (data: RequestData) => Promise<Response>): RequestHandler {
|
||||
export function handleJSONWithData<Response>(
|
||||
handler: (data: RequestData) => Promise<Response>
|
||||
): RequestHandler {
|
||||
return (request, response) => {
|
||||
handler(getData(request))
|
||||
.then(data => success(response, data || {}))
|
||||
.catch(e => error(response, e));
|
||||
.then((data) => success(response, data || {}))
|
||||
.catch((e) => error(response, e));
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue