Skip to content

Commit e169f6c

Browse files
committed
try new approach to callback wrapping
1 parent 987e88c commit e169f6c

File tree

6 files changed

+61
-45
lines changed

6 files changed

+61
-45
lines changed

package-lock.json

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@manwaring/lambda-wrapper",
33
"description": "A lambda handler wrapper to abstract common functionality and provide useful defaults",
4-
"version": "1.0.4",
4+
"version": "1.0.5",
55
"scripts": {
66
"publish-please-dry-run": "publish-please --dry-run",
77
"publish-please": "publish-please",

src/api/responses.test.ts

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,55 @@
1-
import createEvent from '@serverless/event-mocks';
2-
import { success, error, invalid, redirect } from './responses';
1+
import { Responses } from './responses';
2+
import { Metrics } from '../common';
33

44
describe('API responses', () => {
5-
// @ts-ignore
6-
const event = createEvent('aws:apiGateway', {});
5+
const metrics = new Metrics('API Gateway');
6+
const callback = jest.fn((err, result) => (err ? new Error(err) : result));
7+
const responses = new Responses(metrics, callback);
8+
9+
beforeEach(() => jest.resetAllMocks());
710

811
it('Handles success response', () => {
9-
expect(success('success')).toEqual({
12+
responses.success('success');
13+
expect(callback).toHaveBeenCalledWith(null, {
1014
body: JSON.stringify('success'),
1115
headers: { 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Credentials': true },
1216
statusCode: 200
1317
});
1418
});
1519

1620
it('Handles success response without payload', () => {
17-
expect(success()).toEqual({
21+
responses.success();
22+
expect(callback).toHaveBeenCalledWith(null, {
1823
headers: { 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Credentials': true },
1924
statusCode: 200
2025
});
2126
});
2227

2328
it('Handles error response', () => {
24-
expect(() => error('error')).toThrow('error');
29+
responses.error('error');
30+
expect(callback).toHaveBeenCalledWith(new Error('error'));
2531
});
2632

2733
it('Handles invalid response', () => {
28-
expect(invalid(['invalid'])).toEqual({
34+
responses.invalid(['invalid']);
35+
expect(callback).toHaveBeenCalledWith(null, {
2936
body: JSON.stringify({ errors: ['invalid'] }),
3037
headers: { 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Credentials': true },
3138
statusCode: 400
3239
});
3340
});
3441

3542
it('Handles invalid response without validation errors', () => {
36-
expect(invalid()).toEqual({
43+
responses.invalid();
44+
expect(callback).toHaveBeenCalledWith(null, {
3745
headers: { 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Credentials': true },
3846
statusCode: 400
3947
});
4048
});
4149

4250
it('Handles redirect response', () => {
43-
expect(redirect('url')).toEqual({
51+
responses.redirect('url');
52+
expect(callback).toHaveBeenCalledWith(null, {
4453
headers: { 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Credentials': true, Location: 'url' },
4554
statusCode: 302
4655
});

src/api/responses.ts

Lines changed: 28 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,41 @@
1+
import { Callback } from 'aws-lambda';
12
import { Metrics } from '../common';
23

3-
const metrics = new Metrics('API Gateway');
4-
54
const HEADERS = {
65
'Access-Control-Allow-Origin': '*',
76
'Access-Control-Allow-Credentials': true
87
};
98

10-
export function success(payload?: any) {
11-
const response = { statusCode: 200, headers: HEADERS };
12-
if (payload) {
13-
response['body'] = JSON.stringify(payload);
9+
export class Responses {
10+
constructor(private metrics: Metrics, private callback: Callback) {}
11+
12+
success(payload?: any) {
13+
const response = { statusCode: 200, headers: HEADERS };
14+
if (payload) {
15+
response['body'] = JSON.stringify(payload);
16+
}
17+
this.metrics.success(payload);
18+
this.callback(null, response);
1419
}
15-
metrics.success(payload);
16-
return response;
17-
}
1820

19-
export function invalid(errors?: string[]) {
20-
const response = { statusCode: 400, headers: HEADERS };
21-
if (errors) {
22-
response['body'] = JSON.stringify({ errors });
21+
invalid(errors?: string[]) {
22+
const response = { statusCode: 400, headers: HEADERS };
23+
if (errors) {
24+
response['body'] = JSON.stringify({ errors });
25+
}
26+
this.metrics.invalid(response);
27+
this.callback(null, response);
2328
}
24-
metrics.invalid(response);
25-
return response;
26-
}
2729

28-
export function redirect(url: string) {
29-
HEADERS['Location'] = url;
30-
const response = { statusCode: 302, headers: HEADERS };
31-
metrics.redirect(response);
32-
return response;
33-
}
30+
redirect(url: string) {
31+
HEADERS['Location'] = url;
32+
const response = { statusCode: 302, headers: HEADERS };
33+
this.metrics.redirect(response);
34+
this.callback(null, response);
35+
}
3436

35-
export function error(error?: any) {
36-
metrics.error(error);
37-
throw new Error(error);
37+
error(error?: any) {
38+
this.metrics.error(error);
39+
this.callback(new Error(error));
40+
}
3841
}

src/api/wrapper.ts

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
1-
import { APIGatewayEvent } from 'aws-lambda';
1+
import { APIGatewayEvent, Context, Callback } from 'aws-lambda';
22
import { Request } from './parser';
3-
import { success, invalid, redirect, error } from './responses';
3+
import { Metrics } from '../common';
4+
import { Responses } from './responses';
5+
6+
const metrics = new Metrics('API Gateway');
47

58
export function api<T extends Function>(fn: T): T {
6-
return <any>function(event: APIGatewayEvent) {
9+
return <any>function(event: APIGatewayEvent, context: Context, callback: Callback) {
10+
const responses = new Responses(metrics, callback);
711
const { body, path, query, auth, headers, testRequest } = new Request(event).getProperties();
812

913
const signature: ApiSignature = {
@@ -14,10 +18,10 @@ export function api<T extends Function>(fn: T): T {
1418
headers,
1519
testRequest,
1620
auth,
17-
success,
18-
invalid,
19-
redirect,
20-
error
21+
success: responses.success,
22+
invalid: responses.invalid,
23+
redirect: responses.redirect,
24+
error: responses.error
2125
};
2226
return fn(signature);
2327
};

src/cloudformation/wrapper.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ export function cloudFormation<T extends Function>(fn: T): T {
1010

1111
const signature: CloudFormationSignature = {
1212
event,
13-
// We need to call these response wrappers so that we can pass in context (necessary for CloudFormation responses) so that
13+
// We need to call these response wrappers so that we can pass in context (necessary for CloudFormation responses) to keep it abstracted from users
1414
success: successWrapper(event, context),
1515
failure: failureWrapper(event, context)
1616
};

0 commit comments

Comments
 (0)