Skip to content

Commit 3179b5c

Browse files
committed
create ASync and Sync Handlers
1 parent b8ee843 commit 3179b5c

File tree

2 files changed

+125
-12
lines changed

2 files changed

+125
-12
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,20 @@
11
import { Handler } from 'aws-lambda';
22

3+
export type SyncHandler<T extends Handler> = (
4+
event: Parameters<T>[0],
5+
context: Parameters<T>[1],
6+
callback: Parameters<T>[2],
7+
) => void;
8+
9+
export type AsyncHandler<T extends Handler> = (
10+
event: Parameters<T>[0],
11+
context: Parameters<T>[1],
12+
) => Promise<NonNullable<Parameters<Parameters<T>[2]>[1]>>;
13+
314
interface LambdaInterface {
4-
handler: Handler
15+
handler: SyncHandler<Handler> | AsyncHandler<Handler>
516
}
617

718
export {
8-
LambdaInterface,
19+
LambdaInterface
920
};
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,125 @@
1+
import { Handler } from 'aws-lambda';
12
import { Callback, Context } from 'aws-lambda';
2-
import { ContextExamples, LambdaInterface } from '../../src';
3+
import { ContextExamples, SyncHandler, AsyncHandler, LambdaInterface } from '../../src';
34

4-
describe('LambdaInterface', () => {
5-
test('it compiles', async () => {
5+
describe('LambdaInterface with arrow function', () => {
6+
test('it compiles when given a callback', async () => {
67
class LambdaFunction implements LambdaInterface {
7-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
8-
// @ts-ignore
9-
public handler<TEvent, TResult>(
10-
_event: TEvent,
11-
context: Context,
12-
_callback: Callback<TResult>,
13-
): void | Promise<TResult> {
8+
9+
public handler: SyncHandler<Handler> = async (_event: unknown, context: Context, _callback: Callback) => {
1410
context.done();
1511
context.fail(new Error('test Error'));
1612
context.succeed('test succeed');
1713
context.getRemainingTimeInMillis();
14+
_callback(null, 'Hello World');
15+
};
16+
}
17+
18+
await new LambdaFunction().handler({}, ContextExamples.helloworldContext, () => console.log('Lambda invoked!'));
19+
});
20+
21+
test('it compiles when not given a callback', async () => {
22+
class LambdaFunction implements LambdaInterface {
23+
24+
public handler: AsyncHandler<Handler> = async (_event: unknown, context: Context) => {
25+
context.getRemainingTimeInMillis();
26+
};
27+
}
28+
29+
await new LambdaFunction().handler({}, ContextExamples.helloworldContext);
30+
});
31+
});
32+
33+
describe('LambdaInterface with standard function', () => {
34+
test('it compiles when given a callback', async () => {
35+
class LambdaFunction implements LambdaInterface {
36+
37+
public handler(_event: unknown, context: Context, _callback: Callback): void {
38+
context.getRemainingTimeInMillis();
39+
_callback(null, 'Hello World');
1840
}
1941
}
2042

2143
await new LambdaFunction().handler({}, ContextExamples.helloworldContext, () => console.log('Lambda invoked!'));
2244
});
45+
46+
test('it compiles when not given a callback', async () => {
47+
class LambdaFunction implements LambdaInterface {
48+
49+
public async handler (_event: unknown, context: Context): Promise<string> {
50+
context.getRemainingTimeInMillis();
51+
52+
return new Promise((resolve) => {
53+
resolve('test promise');
54+
});
55+
}
56+
}
57+
58+
await new LambdaFunction().handler({}, ContextExamples.helloworldContext);
59+
});
60+
61+
type HandlerMethodDecorator = (
62+
target: LambdaInterface,
63+
propertyKey: string | symbol,
64+
descriptor: TypedPropertyDescriptor<SyncHandler<Handler>> | TypedPropertyDescriptor<AsyncHandler<Handler>>
65+
) => void;
66+
67+
class DummyModule {
68+
69+
public dummyDecorator(): HandlerMethodDecorator {
70+
return (target, _propertyKey, descriptor) => {
71+
const originalMethod = descriptor.value;
72+
73+
descriptor.value = ( async (event, context, callback) => {
74+
75+
let result: unknown;
76+
try {
77+
console.log(`Invoking ${String(_propertyKey)}`);
78+
result = await originalMethod?.apply(this, [ event, context, callback ]);
79+
console.log(`Invoked ${String(_propertyKey)}`);
80+
} catch (error) {
81+
throw error;
82+
} finally {
83+
console.log(`Finally from decorator`);
84+
}
85+
86+
return result;
87+
});
88+
89+
return descriptor;
90+
};
91+
}
92+
}
93+
94+
const dummyModule = new DummyModule();
95+
96+
test('decorator without callback compile', async () => {
97+
98+
// WHEN
99+
class LambdaFunction implements LambdaInterface {
100+
101+
@dummyModule.dummyDecorator()
102+
public async handler(_event: unknown, context: Context): Promise<unknown> {
103+
context.getRemainingTimeInMillis();
104+
105+
return 'test';
106+
}
107+
}
108+
109+
await new LambdaFunction().handler({}, ContextExamples.helloworldContext);
110+
});
111+
112+
test('decorator with callback compile', async () => {
113+
114+
// WHEN
115+
class LambdaFunction implements LambdaInterface {
116+
117+
@dummyModule.dummyDecorator()
118+
public handler(_event: unknown, context: Context, _callback: Callback): void {
119+
context.getRemainingTimeInMillis();
120+
}
121+
}
122+
123+
await new LambdaFunction().handler({}, ContextExamples.helloworldContext, () => console.log('Lambda invoked!'));
124+
});
23125
});

0 commit comments

Comments
 (0)