@@ -6,3 +6,83 @@ process AWS data streams.
6
6
``` bash
7
7
yarn add @lifeomic/delta
8
8
```
9
+
10
+ ### ` DynamoStreamHandler `
11
+
12
+ This helper provides an abstraction over a DynamoDB Stream Lambda handler.
13
+
14
+ ``` typescript
15
+ const stream = new DynamoStreamHandler ({
16
+ logger ,
17
+ unmarshall : (object ) => {
18
+ /* ... unmarshall from unknown stream format -> your custom type ... */
19
+ return { id: object .id };
20
+ },
21
+ createRunContext : () => {
22
+ /* ... create the "context", e.g. data sources ... */
23
+ return { doSomething : () => null };
24
+ },
25
+ })
26
+ .onInsert (async (ctx , entity ) => {
27
+ // INSERT actions receive a single strongly typed new entities
28
+ // (entities are typed based on the `unmarshall` function)
29
+ entity .id ;
30
+
31
+ // `ctx` contains the nice result of `createRunContext`
32
+ await ctx .dataSources .doSomething ();
33
+
34
+ // `ctx` contains a logger by default, which already includes niceties like
35
+ // the AWS request id
36
+ ctx .logger .info (' blah blah' );
37
+ })
38
+ // The API is chainable to help with readability
39
+ .onModify (async (ctx , oldEntity , newEntity ) => {
40
+ // MODIFY actions receive strongly typed old + new entities
41
+ oldEntity .id ;
42
+ newEntity .id ;
43
+ })
44
+ .onRemove (async (ctx , oldEntity ) => {
45
+ // REMOVE actions receive a single strongly typed old entity
46
+ oldEntity .id ;
47
+
48
+ ctx .logger .info (' first remove action' );
49
+ })
50
+ // When multiple actions have been added for the same event (e.g. two `onRemove` calls),
51
+ // they are executed in.order.
52
+ .onRemove (async (ctx , oldEntity ) => {
53
+ ctx .logger .info (' second remove action' );
54
+ });
55
+
56
+ // Provides a dead-simple API for creating the Lambda.
57
+ export const handler = stream .lambda ();
58
+ ```
59
+
60
+ ` DynamoStreamHelper ` also comes with a nice helper for testing: ` harness(...) `
61
+
62
+ ``` typescript
63
+ const harness = stream .harness ({
64
+ marshall : () => {
65
+ /* marshall from your custom type -> stream format */
66
+ },
67
+ /* optionally override the logger */
68
+ logger ,
69
+ createRunContext : () => {
70
+ /* optionally override the context, to mock e.g. data sources */
71
+ }
72
+ })
73
+
74
+ test (' something' , async () => {
75
+ // Provides a simple `sendEvent` function
76
+ await harness .sendEvent ({
77
+ records: [
78
+ // Simplified, strongly-typed event types for readability
79
+ { type: ' remove' , entity: ... },
80
+ { type: ' insert' , entity: ... },
81
+ { type: ' modify' , oldEntity: ... , newEntity: ... },
82
+ ]
83
+ })
84
+
85
+ // Also provides access to the underlying run context for assertions + mocking
86
+ expect (harness .context .dataSources .doSomething ).toHaveBeenCalled ()
87
+ })
88
+ ```
0 commit comments