[TEST] : low coverage in lib/apps/api/middlewares
- Dominant language
- TypeScript
- Stars
- 272
- Forks
- 375
- Avg merge
- 3h 22m
- Merged PRs (30d)
- 8
Description
Current API middleware implementations have very low test coverage and contain tightly coupled logic that makes testing, debugging, and maintenance difficult. In particular, validation and error handling paths include complex async flows, repeated schema compilation, and limited observability during request processing.
### Proposed Changes
1. **Validator Caching** (Performance Improvement)
Avoid recompiling AJV validators for every request.
```
class ValidatorCache {
private cache = new Map();
async getValidator(path, method) {
const key = `${path}:${method}`;
if (!this.cache.has(key)) {
this.cache.set(key, await this.compileValidator(path, method));
}
return this.cache.get(key);
}
}
```
2. **Simplified Validation Middleware Flow** :
```
async function validationMiddleware(options) {
return async (req, res, next) => {
try {
sanitizeInput(req.body);
const validate =
await validatorCache.getValidator(options.path, options.method);
if (!validate(req.body)) {
throw new ProblemException({ status: 422 });
}
await validateDocuments(req, options);
next();
} catch (err) {
next(err);
}
};
}
```
3. **Problem Middleware Error Handling**
**Helper utilities**
```
function extractErrorType(type: string): string {
return type.replace('https://api.asyncapi.com/problem/', '');
}
function categorizeError(status: number): 'client' | 'server' {
return status >= 500 ? 'server' : 'client';
}
```
So the simplified middleware flow:
```
function problemMiddleware(error, req, res, next) {
if (res.headersSent) {
return next(error);
}
try {
const problemShape = error.get();
const status = problemShape.status || 500;
problemShape.status = status;
problemShape.title ||= 'Internal server error';
const errorType = extractErrorType(problemShape.type);
const category = categorizeError(status);
logger.error(
`[${req.method}] ${req.path} >> Status:: ${status}, Type:: ${errorType}`,
{ category }
);
const problem = error.toObject({
includeStack: status >= 500,
includeCause: status >= 500,
});
res.status(status).json(problem);
} catch (err) {
next(err);
}
}
```
### Steps to Reproduce:
- `npx nyc npm test`
- `npx nyc report --reporter=html`
- `start coverage/index.html`
- Navigate to `problem.middleware.js`, `validation.middleware.js`
Happy to raise a PR for this if the maintainers approve
Contributor guide
Assessment
This issue has not been assessed yet.