Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue 565 complexity reduction #11

Merged
merged 6 commits into from
May 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/node_modules
/coverage
/.idea
/node_modules
/src/locales
/coverage
151 changes: 4 additions & 147 deletions src/cli/check-routes.ts
Original file line number Diff line number Diff line change
@@ -1,166 +1,23 @@
/* eslint no-console: 0 */
import jobCreator from '../routes/job-creator.js';
import language, {
locale,
} from '../helper/language.js';
import {
DEFAULT_LANGUAGE,
ONE,
EMPTY,
FIRST_ARGUMENT,
} from '../constants.js';
import validateTasks from '../routes/validate-tasks.js';
import taskTypes from '../routes/task-types.js';
import Task from '../routes/task.js';
import Job from '../routes/job.js';
import taskType from '../routes/task-type.js';
import Request from '../routes/request.js';
import logSymbols from 'log-symbols';
import languageKey from '../locales/language-key.js';

const warn = (key: languageKey, ...argList: string[]) => {
console.warn(logSymbols.warning + ' ' + language(key, ...argList,),);
};
const error = (key: languageKey, ...argList: string[]) => {
console.error(logSymbols.error + ' ' + language(key, ...argList,),);
};

// eslint-disable-next-line complexity
const checkMiddleware = (type: 'pre'|'post', route: Task,) => {
if (typeof route[type] === 'undefined') {
return true;
}
const data = route[type];
delete route[type];
if (typeof data !== 'object' || ! Array.isArray(data,)) {
error(`invalid_${ type }_definition`, route.id,);
return false;
}
for (const middleware of data) {
if (typeof middleware !== 'string') {
error(`invalid_${ type }_definition`, route.id,);
return false;
}
}
return true;
};

// eslint-disable-next-line complexity
const checkRequest = (main: Request, id: string,): {
invalid: boolean,
risky: boolean,
} => {
const properties = [
{
name: 'method',
type: 'string',
required: true,
},
{
name: 'headers',
type: 'object',
required: false,
},
{
name: 'cookies',
type: 'object',
required: false,
},
{
name: 'body',
type: [
'string',
'object',
],
required: false,
},
{
name: 'autohandle',
type: 'string',
required: false,
},
{
name: 'url',
type: 'string',
required: true,
},
{
name: 'maxDuration',
type: 'number',
required: false,
},
];
let valid = true;
for (const property of properties) {
if (property.required && typeof main[property.name] === 'undefined') {
error('invalid_request_property', id, property.name,);
valid = false;
} else if (typeof main[property.name] !== property.type) {
error('invalid_request_property', id, property.name,);
valid = false;
delete main[property.name];
} else {
delete main[property.name];
}
}
if (Object.keys(main,).length === EMPTY) {
warn('invalid_request', id,);
return {
invalid: ! valid,
risky: true,
};
}
return {
invalid: ! valid,
risky: false,
};
};

// eslint-disable-next-line complexity
const checkType = (job: Job, type: taskType,) => {
if (typeof job[type] === 'undefined') {
return {
errors: 0,
warnings: 0,
};
}
let errors = 0;
let warnings = 0;
if (job[type].length > EMPTY) {
for (const route of job[type]) {
if (! checkMiddleware('pre', route,)) {
errors ++;
}
if (! checkMiddleware('post', route,)) {
errors ++;
}
const id = route.id;
delete route.id;
const result = checkRequest(route.main, id,);
if (result.invalid) {
errors ++;
}
if (result.risky) {
warnings ++;
}
delete route.main;
for (const key of Object.keys(route,)) {
warn('unknown_route_property', key, id,);
warnings ++;
}
}
}
return {
errors,
warnings,
};
};
import error from '../validation/error.js';
import checkType from '../validation/check-type.js';
import noDuplicateIds from '../validation/no-duplicate-ids.js';
Idrinth marked this conversation as resolved.
Show resolved Hide resolved

// eslint-disable-next-line complexity
export default async(args: string[], cwd: string,): Promise<void> => {
await locale(args[FIRST_ARGUMENT] || DEFAULT_LANGUAGE,);
const job = await jobCreator(cwd,);
validateTasks(ONE, ONE, job.main,);
noDuplicateIds(job.main,);
let errors = 0;
let warnings = 0;
for (const type of taskTypes) {
Expand All @@ -175,6 +32,6 @@
error('validation_warnings', `${ warnings }`,);
}
if (warnings === EMPTY && errors === EMPTY) {
console.log(logSymbols.success + ' ' + language('no_errors_warnings',),);

Check warning on line 35 in src/cli/check-routes.ts

View workflow job for this annotation

GitHub Actions / lint

Unexpected console statement
}
};
2 changes: 1 addition & 1 deletion src/routes/middleware-loader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,6 @@ const resolve = (path: string,): string => {
};
const load = async(path: string,): Promise<Middleware> => {
const req = cache[path] || (cache[path] = resolve(path,));
return new (await include(req,)) as Middleware;
return new (await include(req,))() as Middleware;
Idrinth marked this conversation as resolved.
Show resolved Hide resolved
};
export default load;
16 changes: 4 additions & 12 deletions src/routes/validate-tasks.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,10 @@
import Task from './task.js';
import language from '../helper/language.js';
import language from './helper/language.js';
import {
EMPTY,
} from '../constants.js';
} from './constants.js';
Idrinth marked this conversation as resolved.
Show resolved Hide resolved
import noDuplicateIds from './no-duplicate-ids.js';

const noDuplicateIDs = (tasks: Array<Task>,) => {
const ids: Array<string> = [];
for (const task of tasks) {
if (ids.includes(task.id,)) {
throw new Error(language('duplicate_task_id', task.id,),);
}
ids.push(task.id,);
}
};
const executableAmount = (
repetitions: number,
threads: number,
Expand All @@ -29,5 +21,5 @@ export default function validateTasks(
tasks: Array<Task>,
): void {
executableAmount(repetitions, threads, tasks,);
noDuplicateIDs(tasks,);
noDuplicateIds(tasks,);
Idrinth marked this conversation as resolved.
Show resolved Hide resolved
}
23 changes: 23 additions & 0 deletions src/validation/check-middleware.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import Task from '../task.js';
import error from './error.js';
Idrinth marked this conversation as resolved.
Show resolved Hide resolved

const checkMiddleware = (type: 'pre' | 'post', route: Task,) => {
Idrinth marked this conversation as resolved.
Show resolved Hide resolved
if (typeof route[type] === 'undefined') {
return true;
}
const data = route[type];
delete route[type];
if (typeof data !== 'object' || ! Array.isArray(data,)) {
error(`invalid_${ type }_definition`, route.id,);
return false;
}
for (const middleware of data) {
if (typeof middleware !== 'string') {
error(`invalid_${ type }_definition`, route.id,);
return false;
}
}
return true;
};

export default checkMiddleware;
89 changes: 89 additions & 0 deletions src/validation/check-request.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import Request from '../request.js';
import error from './error.js';
import {
EMPTY,
} from '../constants.js';
import warn from './warn.js';

interface Property {
name: string;
type: string|string[];
required: boolean;
}

const properties: Property[] = [
{
name: 'method',
type: 'string',
required: true,
},
{
name: 'headers',
type: 'object',
required: false,
},
{
name: 'cookies',
type: 'object',
required: false,
},
{
name: 'body',
type: [
'string',
'object',
],
required: false,
},
{
name: 'autohandle',
type: 'string',
required: false,
},
{
name: 'url',
type: 'string',
required: true,
},
{
name: 'maxDuration',
type: 'number',
required: false,
},
];

const validateProperty = (property: Property, id: string, main: Request,) => {
if (property.required && typeof main[property.name] === 'undefined') {
error('invalid_request_property', id, property.name,);
return false;
}
const allowedTypes: string[] = Array.isArray(property.type,) ? property.type : [ property.type, ];

Check warning on line 60 in src/validation/check-request.ts

View workflow job for this annotation

GitHub Actions / lint

This line has a length of 100. Maximum allowed is 80
Idrinth marked this conversation as resolved.
Show resolved Hide resolved
if (! allowedTypes.includes(typeof main[property.name],)) {
error('invalid_request_property', id, property.name,);
delete main[property.name];
return false;
}
delete main[property.name];
return true;
};
const checkRequest = (main: Request, id: string,): {
invalid: boolean,
risky: boolean,
} => {
let valid = true;
for (const property of properties) {
valid = validateProperty(property, id, main,) && valid;
}
if (Object.keys(main,).length !== EMPTY) {
Idrinth marked this conversation as resolved.
Show resolved Hide resolved
warn('invalid_request', id,);
return {
invalid: ! valid,
risky: true,
};
}
return {
invalid: ! valid,
risky: false,
};
};
export default checkRequest;
49 changes: 49 additions & 0 deletions src/validation/check-type.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import Job from '../job.js';
import taskType from '../task-type.js';
import {
EMPTY,
} from '../constants.js';
import checkRequest from './check-request.js';
import warn from './warn.js';
import checkMiddleware from './check-middleware.js';

const checkType = (job: Job, type: taskType,) => {
Idrinth marked this conversation as resolved.
Show resolved Hide resolved
if (typeof job[type] === 'undefined') {
return {
errors: 0,
warnings: 0,
};
}
let errors = 0;
let warnings = 0;
if (job[type].length > EMPTY) {
for (const route of job[type]) {
if (! checkMiddleware('pre', route,)) {
errors ++;
}
if (! checkMiddleware('post', route,)) {
errors ++;
}
const id = route.id;
delete route.id;
const result = checkRequest(route.main, id,);
if (result.invalid) {
errors ++;
}
if (result.risky) {
warnings ++;
}
delete route.main;
for (const key of Object.keys(route,)) {
warn('unknown_route_property', key, id,);
warnings ++;
}
}
}
return {
errors,
warnings,
};
};

export default checkType;
10 changes: 10 additions & 0 deletions src/validation/error.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/* eslint no-console: 0 */
Idrinth marked this conversation as resolved.
Show resolved Hide resolved
import language from '../helper/language.js';
import logSymbols from 'log-symbols';
import languageKey from '../locales/language-key.js';

const error = (key: languageKey, ...argList: string[]) => {
console.error(logSymbols.error + ' ' + language(key, ...argList,),);
};

export default error;
Loading
Loading