Skip to content
This repository was archived by the owner on Jun 22, 2021. It is now read-only.

Commit a2e69dc

Browse files
committed
fix(getEntities): Fixes issue with invalid limit.
1 parent 3fd7f78 commit a2e69dc

14 files changed

+59
-15
lines changed

readme.md

+2
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ export interface TodoEntity extends Entity {
2727
import factory from '@js-entity-repos/express/dist/factory';
2828

2929
const todosFacade = factory<TodoEntity>({
30+
// Optional property that determines the default pagination limit.
31+
defaultPaginationLimit: 10,
3032
// Optional property that catches errors from handlers.
3133
errorCatcher: (handler) => (req, res) => {
3234
handler(req, res).catch((err) => {

src/FacadeConfig.ts

+1
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,5 @@ import ErrorCatcher from './utils/ErrorCatcher';
55
export default interface FacadeConfig<E extends Entity> {
66
readonly service: Facade<E>;
77
readonly errorCatcher: ErrorCatcher;
8+
readonly defaultPaginationLimit: number;
89
}

src/FactoryConfig.ts

+1
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,5 @@ import ErrorCatcher from './utils/ErrorCatcher';
55
export default interface FactoryConfig<E extends Entity> {
66
readonly service: Facade<E>;
77
readonly errorCatcher?: ErrorCatcher;
8+
readonly defaultPaginationLimit?: number;
89
}

src/factory.test.ts

+8-1
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ facadeTest(axiosFactory<TestEntity>({
4343
}));
4444

4545
describe('facade', () => {
46-
it('should not throw JSON error', async () => {
46+
it('should not throw errors when not using any query params', async () => {
4747
const response = await axiosClient.get('/');
4848
assert.equal(response.status, OK);
4949
});
@@ -54,4 +54,11 @@ describe('facade', () => {
5454
assert.equal(err.response.status, BAD_REQUEST);
5555
});
5656
});
57+
it('should throw number error when using invalid limit', async () => {
58+
await axiosClient.get('/?limit=invalid_number').then((response) => {
59+
return { response };
60+
}).catch((err) => {
61+
assert.equal(err.response.status, BAD_REQUEST);
62+
});
63+
});
5764
});

src/factory.ts

+1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import catchErrors from './utils/catchErrors';
1515

1616
export default <E extends Entity>(factoryConfig: FactoryConfig<E>): Router => {
1717
const facadeConfig: FacadeConfig<E> = {
18+
defaultPaginationLimit: 10,
1819
errorCatcher: catchErrors,
1920
...factoryConfig,
2021
};

src/functions/getEntities.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,17 @@ import { OK } from 'http-status-codes';
44
import FacadeConfig from '../FacadeConfig';
55
import catchErrors from '../utils/catchErrors';
66
import getJsonQueryParam from '../utils/getJsonQueryParam';
7+
import getNumberQueryParam from '../utils/getNumberQueryParam';
78

89
export default <E extends Entity>(config: FacadeConfig<E>) => {
910
return catchErrors(async (req: Request, res: Response) => {
11+
const limit = getNumberQueryParam(req.query, 'limit', config.defaultPaginationLimit);
1012
const result = await config.service.getEntities({
1113
filter: getJsonQueryParam(req.query, 'filter'),
1214
pagination: {
1315
cursor: req.query.cursor,
1416
forward: req.query.forward === 'true',
15-
limit: Number(req.query.limit),
17+
limit,
1618
},
1719
sort: getJsonQueryParam(req.query, 'sort'),
1820
});

src/utils/JsonError.ts

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// tslint:disable:no-class
2+
import { BaseError } from 'make-error';
3+
4+
export default class JsonError extends BaseError {
5+
constructor(public data: any, public path: string[]) {
6+
super();
7+
}
8+
}

src/utils/JsonSyntaxError.ts

-8
This file was deleted.

src/utils/NumberError.ts

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// tslint:disable:no-class
2+
import { BaseError } from 'make-error';
3+
4+
export default class NumberError extends BaseError {
5+
constructor(public data: any, public path: string[]) {
6+
super();
7+
}
8+
}

src/utils/Query.ts

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export default interface Query {
2+
readonly [k: string]: string | undefined;
3+
}

src/utils/catchErrors.ts

+6-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@ import ConflictingEntityError from '@js-entity-repos/core/dist/errors/Conflictin
22
import MissingEntityError from '@js-entity-repos/core/dist/errors/MissingEntityError';
33
import { BAD_REQUEST, CONFLICT, INTERNAL_SERVER_ERROR, NOT_FOUND } from 'http-status-codes';
44
import ErrorCatcher from './ErrorCatcher';
5-
import JsonSyntaxError from './JsonSyntaxError';
5+
import JsonError from './JsonError';
6+
import NumberError from './NumberError';
67

78
const errorCatcher: ErrorCatcher = (handler) => {
89
return (req, res) => {
@@ -13,7 +14,10 @@ const errorCatcher: ErrorCatcher = (handler) => {
1314
if (err instanceof MissingEntityError) {
1415
return res.status(NOT_FOUND).send();
1516
}
16-
if (err instanceof JsonSyntaxError) {
17+
if (err instanceof JsonError) {
18+
return res.status(BAD_REQUEST).send();
19+
}
20+
if (err instanceof NumberError) {
1721
return res.status(BAD_REQUEST).send();
1822
}
1923
/* istanbul ignore next */

src/utils/getJsonQueryParam.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import parseJson from './parseJson';
2+
import Query from './Query';
23

3-
export default (data: { readonly [k: string]: string | undefined }, paramName: string) => {
4+
export default (data: Query, paramName: string) => {
45
const paramValue = data[paramName];
56
return paramValue === undefined ? undefined : parseJson(paramValue, [paramName]);
67
};

src/utils/getNumberQueryParam.ts

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import NumberError from './NumberError';
2+
import Query from './Query';
3+
4+
export default <T>(query: Query, paramName: string, defaultValue: T) => {
5+
const paramValue = query[paramName];
6+
if (paramValue === undefined) {
7+
return defaultValue;
8+
}
9+
const parsedParamValue = Number(paramValue);
10+
if (isNaN(parsedParamValue)) {
11+
throw new NumberError(paramValue, [paramName]);
12+
}
13+
return parsedParamValue;
14+
};

src/utils/parseJson.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
import JsonSyntaxError from './JsonSyntaxError';
1+
import JsonError from './JsonError';
22

33
export default (data: string, path: string[]) => {
44
try {
55
return JSON.parse(data);
66
} catch (err) {
77
if (err instanceof SyntaxError) {
8-
throw new JsonSyntaxError(path);
8+
throw new JsonError(data, path);
99
}
1010
/* istanbul ignore next */
1111
throw err;

0 commit comments

Comments
 (0)