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

Commit 928e7dd

Browse files
authored
feat: Simplifies error handling. (#5)
BREAKING CHANGE: `errorCatcher` removed from `FactoryConfig` in favour of `handleTransaction`.
1 parent 23d7cf5 commit 928e7dd

20 files changed

+205
-118
lines changed

package-lock.json

Lines changed: 14 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@
2626
},
2727
"dependencies": {
2828
"@js-entity-repos/core": "^6.0.2",
29-
"http-status-codes": "^1.3.0"
29+
"http-status-codes": "^1.3.0",
30+
"uuid": "^3.2.1"
3031
},
3132
"devDependencies": {
3233
"@ht2-labs/semantic-release": "1.0.31",
@@ -37,6 +38,7 @@
3738
"@types/express": "4.11.1",
3839
"@types/mocha": "2.2.48",
3940
"@types/source-map-support": "0.4.0",
41+
"@types/uuid": "3.4.3",
4042
"assert-rejects": "0.1.1",
4143
"axios": "0.18.0",
4244
"dotenv": "5.0.1",

readme.md

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,17 @@ const todosFacade = factory<TodoEntity>({
3333
},
3434
// Optional property.
3535
defaultPaginationLimit: 10,
36-
// Optional property that catches errors from handlers.
37-
errorCatcher: (handler) => (req, res) => {
38-
handler(req, res).catch((err) => {
39-
res.status(500).send();
40-
});
41-
},
36+
// Optional property to handle transactions.
37+
handleTransaction: async ({ req, res }, handler) => {
38+
// The transactionId allow items found in logs to be matched with responses to users.
39+
const transactionId = uuid();
40+
try {
41+
await handler({ transactionId });
42+
} catch (err) {
43+
console.error({ err, req, res, transactionId})
44+
res.status(500).send(transactionId);
45+
}
46+
};
4247
service,
4348
});
4449
```

src/FacadeConfig.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
import Facade from '@js-entity-repos/core/dist/Facade';
22
import Entity from '@js-entity-repos/core/dist/types/Entity';
33
import Filter from '@js-entity-repos/core/dist/types/Filter';
4-
import ErrorCatcher from './utils/ErrorCatcher';
4+
import TransactionHandler from './utils/TransactionHandler';
55

66
export default interface FacadeConfig<E extends Entity> {
77
readonly constructFilter: (filter: Filter<E>) => any;
88
readonly service: Facade<E>;
9-
readonly errorCatcher: ErrorCatcher;
9+
readonly handleTransaction: TransactionHandler;
1010
readonly defaultPaginationLimit: number;
1111
}

src/FactoryConfig.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
import Facade from '@js-entity-repos/core/dist/Facade';
22
import Entity from '@js-entity-repos/core/dist/types/Entity';
33
import { Filter } from '@js-entity-repos/core/dist/types/Filter';
4-
import ErrorCatcher from './utils/ErrorCatcher';
4+
import TransactionHandler from './utils/TransactionHandler';
55

66
export default interface FactoryConfig<E extends Entity> {
77
readonly constructFilter?: (filter: Filter<E>) => any;
88
readonly service: Facade<E>;
9-
readonly errorCatcher?: ErrorCatcher;
9+
readonly handleTransaction?: TransactionHandler;
1010
readonly defaultPaginationLimit?: number;
1111
}

src/factory.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,13 @@ import patchEntities from './functions/patchEntities';
1111
import removeEntities from './functions/removeEntities';
1212
import removeEntity from './functions/removeEntity';
1313
import replaceEntity from './functions/replaceEntity';
14-
import catchErrors from './utils/catchErrors';
14+
import handleTransaction from './utils/handleTransaction';
1515

1616
export default <E extends Entity>(factoryConfig: FactoryConfig<E>): Router => {
1717
const facadeConfig: FacadeConfig<E> = {
1818
constructFilter: (filter) => filter,
1919
defaultPaginationLimit: 10,
20-
errorCatcher: catchErrors,
20+
handleTransaction,
2121
...factoryConfig,
2222
};
2323
const router = Router();

src/functions/countEntities.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,15 @@ import Entity from '@js-entity-repos/core/dist/types/Entity';
22
import { Request, Response } from 'express';
33
import { OK } from 'http-status-codes';
44
import FacadeConfig from '../FacadeConfig';
5-
import catchErrors from '../utils/catchErrors';
65
import getJsonQueryParam from '../utils/getJsonQueryParam';
76

87
export default <E extends Entity>(config: FacadeConfig<E>) => {
9-
return catchErrors(async (req: Request, res: Response) => {
10-
const { count } = await config.service.countEntities({
11-
filter: config.constructFilter(getJsonQueryParam(req.query, 'filter')),
8+
return async (req: Request, res: Response) => {
9+
await config.handleTransaction({ req, res }, async () => {
10+
const { count } = await config.service.countEntities({
11+
filter: config.constructFilter(getJsonQueryParam(req.query, 'filter')),
12+
});
13+
res.status(OK).json(count);
1214
});
13-
res.status(OK).json(count);
14-
});
15+
};
1516
};

src/functions/createEntity.ts

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,15 @@ import Entity from '@js-entity-repos/core/dist/types/Entity';
22
import { Request, Response } from 'express';
33
import { OK } from 'http-status-codes';
44
import FacadeConfig from '../FacadeConfig';
5-
import catchErrors from '../utils/catchErrors';
65

76
export default <E extends Entity>(config: FacadeConfig<E>) => {
8-
return catchErrors(async (req: Request, res: Response) => {
9-
const { entity } = await config.service.createEntity({
10-
entity: req.body,
11-
id: req.body.id,
7+
return async (req: Request, res: Response) => {
8+
await config.handleTransaction({ req, res }, async () => {
9+
const { entity } = await config.service.createEntity({
10+
entity: req.body,
11+
id: req.body.id,
12+
});
13+
res.status(OK).json(entity);
1214
});
13-
res.status(OK).json(entity);
14-
});
15+
};
1516
};

src/functions/getEntities.ts

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,29 +2,30 @@ import Entity from '@js-entity-repos/core/dist/types/Entity';
22
import { Request, Response } from 'express';
33
import { OK } from 'http-status-codes';
44
import FacadeConfig from '../FacadeConfig';
5-
import catchErrors from '../utils/catchErrors';
65
import getJsonQueryParam from '../utils/getJsonQueryParam';
76
import getNumberQueryParam from '../utils/getNumberQueryParam';
87

98
export default <E extends Entity>(config: FacadeConfig<E>) => {
10-
return catchErrors(async (req: Request, res: Response) => {
11-
const limit = getNumberQueryParam(req.query, 'limit', config.defaultPaginationLimit);
12-
const result = await config.service.getEntities({
13-
filter: config.constructFilter(getJsonQueryParam(req.query, 'filter')),
14-
pagination: {
15-
cursor: req.query.cursor,
16-
forward: req.query.forward === 'true',
17-
limit,
18-
},
19-
sort: getJsonQueryParam(req.query, 'sort'),
9+
return async (req: Request, res: Response) => {
10+
await config.handleTransaction({ req, res }, async () => {
11+
const limit = getNumberQueryParam(req.query, 'limit', config.defaultPaginationLimit);
12+
const result = await config.service.getEntities({
13+
filter: config.constructFilter(getJsonQueryParam(req.query, 'filter')),
14+
pagination: {
15+
cursor: req.query.cursor,
16+
forward: req.query.forward === 'true',
17+
limit,
18+
},
19+
sort: getJsonQueryParam(req.query, 'sort'),
20+
});
21+
res.status(OK);
22+
if (result.nextCursor !== undefined) {
23+
res.setHeader('x-entities-next-cursor', result.nextCursor);
24+
}
25+
if (result.previousCursor !== undefined) {
26+
res.setHeader('x-entities-previous-cursor', result.previousCursor);
27+
}
28+
res.json(result.entities);
2029
});
21-
res.status(OK);
22-
if (result.nextCursor !== undefined) {
23-
res.setHeader('x-entities-next-cursor', result.nextCursor);
24-
}
25-
if (result.previousCursor !== undefined) {
26-
res.setHeader('x-entities-previous-cursor', result.previousCursor);
27-
}
28-
res.json(result.entities);
29-
});
30+
};
3031
};

src/functions/getEntity.ts

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,16 @@ import Entity from '@js-entity-repos/core/dist/types/Entity';
22
import { Request, Response } from 'express';
33
import { OK } from 'http-status-codes';
44
import FacadeConfig from '../FacadeConfig';
5-
import catchErrors from '../utils/catchErrors';
65
import getJsonQueryParam from '../utils/getJsonQueryParam';
76

87
export default <E extends Entity>(config: FacadeConfig<E>) => {
9-
return catchErrors(async (req: Request, res: Response) => {
10-
const { entity } = await config.service.getEntity({
11-
filter: config.constructFilter(getJsonQueryParam(req.query, 'filter')),
12-
id: req.params.id,
8+
return async (req: Request, res: Response) => {
9+
await config.handleTransaction({ req, res }, async () => {
10+
const { entity } = await config.service.getEntity({
11+
filter: config.constructFilter(getJsonQueryParam(req.query, 'filter')),
12+
id: req.params.id,
13+
});
14+
res.status(OK).json(entity);
1315
});
14-
res.status(OK).json(entity);
15-
});
16+
};
1617
};

0 commit comments

Comments
 (0)