@lafken/event 0.6.4 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +209 -83
- package/lib/main/event/event.d.ts +18 -0
- package/lib/main/event/event.js +18 -0
- package/lib/main/rule/rule.d.ts +46 -0
- package/lib/main/rule/rule.js +46 -0
- package/lib/resolver/resolver.js +2 -2
- package/lib/resolver/resolver.types.d.ts +1 -1
- package/lib/resolver/rule/rule.d.ts +1 -1
- package/lib/resolver/rule/rule.js +4 -4
- package/lib/resolver/rule/rule.types.d.ts +1 -1
- package/package.json +36 -15
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @lafken/event
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Listen and react to Amazon EventBridge events using TypeScript decorators. `@lafken/event` lets you define event rules with pattern-based filtering and automatically connects them to Lambda functions. Supports custom events, S3 notifications, and DynamoDB stream events.
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
@@ -8,88 +8,104 @@
|
|
|
8
8
|
npm install @lafken/event
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
-
##
|
|
11
|
+
## Getting Started
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
In its configuration, you can define one or more event buses. If no event bus is provided, the default EventBridge bus will be used for communication.
|
|
13
|
+
Define an event rule class with `@EventRule`, add `@Rule` methods with event patterns, and register everything through `EventRuleResolver`:
|
|
15
14
|
|
|
16
15
|
```typescript
|
|
17
|
-
import {
|
|
16
|
+
import { createApp, createModule } from '@lafken/main';
|
|
17
|
+
import { EventRuleResolver } from '@lafken/event/resolver';
|
|
18
|
+
import { EventRule, Rule, Event } from '@lafken/event/main';
|
|
18
19
|
|
|
20
|
+
// 1. Define event handlers
|
|
21
|
+
@EventRule()
|
|
22
|
+
export class OrderEvents {
|
|
23
|
+
@Rule({
|
|
24
|
+
pattern: {
|
|
25
|
+
source: 'orders',
|
|
26
|
+
detailType: ['order.created'],
|
|
27
|
+
},
|
|
28
|
+
})
|
|
29
|
+
onOrderCreated(@Event() event: any) {
|
|
30
|
+
console.log('New order:', event);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// 2. Register in a module
|
|
35
|
+
const orderModule = createModule({
|
|
36
|
+
name: 'order',
|
|
37
|
+
resources: [OrderEvents],
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
// 3. Add the resolver to the app
|
|
19
41
|
createApp({
|
|
20
|
-
name: '
|
|
21
|
-
resolvers: [
|
|
22
|
-
|
|
23
|
-
busName: 'awesome-event-bus',
|
|
24
|
-
extend: ({ eventBus }) => {
|
|
25
|
-
// ... extend the event bus
|
|
26
|
-
},
|
|
27
|
-
}),
|
|
28
|
-
],
|
|
29
|
-
...
|
|
42
|
+
name: 'my-app',
|
|
43
|
+
resolvers: [new EventRuleResolver({ busName: 'my-event-bus' })],
|
|
44
|
+
modules: [orderModule],
|
|
30
45
|
});
|
|
31
46
|
```
|
|
32
47
|
|
|
33
|
-
|
|
48
|
+
Each `@Rule` method becomes an independent Lambda function triggered by matching EventBridge events. The event payload is automatically passed through `$.detail`.
|
|
49
|
+
|
|
50
|
+
## Features
|
|
51
|
+
|
|
52
|
+
### Event Rule Class
|
|
34
53
|
|
|
35
|
-
|
|
54
|
+
Use the `@EventRule` decorator to group related event handlers in a single class:
|
|
36
55
|
|
|
37
56
|
```typescript
|
|
38
|
-
@
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
export class
|
|
57
|
+
import { EventRule, Rule, Event } from '@lafken/event/main';
|
|
58
|
+
|
|
59
|
+
@EventRule()
|
|
60
|
+
export class InventoryEvents {
|
|
42
61
|
@Rule({
|
|
43
|
-
bus: 'awesome-event-bus',
|
|
44
62
|
pattern: {
|
|
45
|
-
source: '
|
|
63
|
+
source: 'inventory',
|
|
64
|
+
detailType: ['stock.updated'],
|
|
46
65
|
},
|
|
47
66
|
})
|
|
48
|
-
|
|
49
|
-
// ...
|
|
50
|
-
}
|
|
51
|
-
}
|
|
67
|
+
onStockUpdate(@Event() event: any) { }
|
|
52
68
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
})
|
|
69
|
+
@Rule({
|
|
70
|
+
pattern: {
|
|
71
|
+
source: 'inventory',
|
|
72
|
+
detailType: ['stock.depleted'],
|
|
73
|
+
},
|
|
74
|
+
})
|
|
75
|
+
onStockDepleted(@Event() event: any) { }
|
|
76
|
+
}
|
|
59
77
|
```
|
|
60
78
|
|
|
61
|
-
|
|
79
|
+
### Custom Events
|
|
62
80
|
|
|
63
|
-
|
|
64
|
-
The @Rule decorator allows you to define an event pattern by specifying the event source and applying filters on detail and detailType.
|
|
81
|
+
Define rules that match custom events by specifying `source`, `detailType`, and `detail` filters:
|
|
65
82
|
|
|
66
83
|
```typescript
|
|
67
84
|
@Rule({
|
|
68
85
|
pattern: {
|
|
69
|
-
source: '
|
|
86
|
+
source: 'payments',
|
|
87
|
+
detailType: ['payment.completed', 'payment.refunded'],
|
|
70
88
|
detail: {
|
|
71
|
-
|
|
89
|
+
currency: ['USD', 'EUR'],
|
|
72
90
|
},
|
|
73
|
-
detailType: ['CREATE', 'UPDATE'],
|
|
74
91
|
},
|
|
75
92
|
})
|
|
76
|
-
|
|
93
|
+
onPaymentEvent(@Event() event: any) {
|
|
94
|
+
// Triggered only for USD or EUR payments
|
|
95
|
+
}
|
|
77
96
|
```
|
|
78
97
|
|
|
79
|
-
|
|
80
|
-
To access the payload sent by an event, you must use the @Event decorator. This decorator automatically maps the event’s inputPath to $.detail, allowing you to receive the event data directly as a parameter.
|
|
98
|
+
#### Pattern Fields
|
|
81
99
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
```
|
|
88
|
-
### S3 integrations
|
|
89
|
-
Event rules also support integration with Amazon S3 through EventBridge-enabled bucket notifications.
|
|
90
|
-
When this integration is enabled, S3 events are delivered to EventBridge, allowing fine-grained filtering based on event metadata such as the bucket name, object key, and event type.
|
|
100
|
+
| Field | Type | Description |
|
|
101
|
+
| ------------ | ---------- | ---------------------------------------------------- |
|
|
102
|
+
| `source` | `string` | Event source identifier (required) |
|
|
103
|
+
| `detailType` | `string[]` | Event type names to match |
|
|
104
|
+
| `detail` | `object` | Attribute-level filtering on the event payload |
|
|
91
105
|
|
|
92
|
-
|
|
106
|
+
### S3 Integration
|
|
107
|
+
|
|
108
|
+
Listen for S3 bucket notifications delivered through EventBridge. Set `integration: 's3'` and define a pattern matching the S3 event structure:
|
|
93
109
|
|
|
94
110
|
```typescript
|
|
95
111
|
@Rule({
|
|
@@ -98,65 +114,175 @@ To enable S3 integration within an event rule, set the integration property to '
|
|
|
98
114
|
detailType: ['Object Created'],
|
|
99
115
|
detail: {
|
|
100
116
|
bucket: {
|
|
101
|
-
name: ['
|
|
117
|
+
name: ['uploads-bucket'],
|
|
102
118
|
},
|
|
103
119
|
object: {
|
|
104
|
-
key: [
|
|
105
|
-
{
|
|
106
|
-
prefix: 'test.json',
|
|
107
|
-
},
|
|
108
|
-
],
|
|
120
|
+
key: [{ prefix: 'images/' }],
|
|
109
121
|
},
|
|
110
122
|
},
|
|
111
123
|
},
|
|
112
124
|
})
|
|
113
|
-
|
|
114
|
-
//
|
|
125
|
+
onImageUploaded(@Event() event: any) {
|
|
126
|
+
// Triggered when a new object is created under images/
|
|
115
127
|
}
|
|
116
128
|
```
|
|
117
129
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
130
|
+
#### S3 Pattern Options
|
|
131
|
+
|
|
132
|
+
| Field | Type | Description |
|
|
133
|
+
| --------------------- | ---------------------------------- | -------------------------------------------- |
|
|
134
|
+
| `detailType` | `S3DetailType[]` | `'Object Created'` or `'Object Deleted'` |
|
|
135
|
+
| `detail.bucket.name` | `string[]` | Bucket names to match |
|
|
136
|
+
| `detail.object.key` | `(string \| S3ObjectKey)[]` | Object keys or prefix/suffix patterns |
|
|
121
137
|
|
|
122
|
-
|
|
138
|
+
Object key filters support `prefix` and `suffix` matching:
|
|
139
|
+
|
|
140
|
+
```typescript
|
|
141
|
+
detail: {
|
|
142
|
+
object: {
|
|
143
|
+
key: [
|
|
144
|
+
{ prefix: 'uploads/' },
|
|
145
|
+
{ suffix: '.pdf' },
|
|
146
|
+
'exact-filename.txt',
|
|
147
|
+
],
|
|
148
|
+
},
|
|
149
|
+
}
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
### DynamoDB Integration
|
|
153
|
+
|
|
154
|
+
Consume events from DynamoDB Streams routed through EventBridge. The target table must have streams enabled (see `@lafken/dynamo` stream configuration). Set `integration: 'dynamodb'` and use `source` to specify the table name:
|
|
123
155
|
|
|
124
156
|
```typescript
|
|
125
157
|
@Rule({
|
|
126
158
|
integration: 'dynamodb',
|
|
127
159
|
pattern: {
|
|
128
|
-
source: '
|
|
160
|
+
source: 'customers',
|
|
129
161
|
detail: {
|
|
130
162
|
eventName: ['INSERT', 'MODIFY'],
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
prefix: 'awesome',
|
|
134
|
-
},
|
|
163
|
+
newImage: {
|
|
164
|
+
status: ['active'],
|
|
135
165
|
},
|
|
136
166
|
},
|
|
137
167
|
},
|
|
138
168
|
})
|
|
139
|
-
|
|
140
|
-
//
|
|
169
|
+
onCustomerChange(@Event() event: any) {
|
|
170
|
+
// Triggered on INSERT or MODIFY where status is 'active'
|
|
171
|
+
}
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
#### DynamoDB Pattern Options
|
|
175
|
+
|
|
176
|
+
| Field | Type | Description |
|
|
177
|
+
| ------------------ | --------------------------------------- | --------------------------------------------- |
|
|
178
|
+
| `source` | `string` | DynamoDB table name |
|
|
179
|
+
| `detail.eventName` | `('INSERT' \| 'MODIFY' \| 'REMOVE')[]` | Stream event types to match |
|
|
180
|
+
| `detail.keys` | `DynamoAttributeFilters` | Filter by primary key values |
|
|
181
|
+
| `detail.newImage` | `DynamoAttributeFilters` | Filter by new item attributes (after change) |
|
|
182
|
+
| `detail.oldImage` | `DynamoAttributeFilters` | Filter by old item attributes (before change) |
|
|
183
|
+
|
|
184
|
+
Attribute filters support EventBridge content-based filtering patterns:
|
|
185
|
+
|
|
186
|
+
```typescript
|
|
187
|
+
detail: {
|
|
188
|
+
keys: {
|
|
189
|
+
email: ['user@example.com'],
|
|
190
|
+
age: [{ numeric: ['>', 18] }],
|
|
191
|
+
},
|
|
192
|
+
newImage: {
|
|
193
|
+
name: [{ prefix: 'A' }],
|
|
194
|
+
role: [{ 'anything-but': 'admin' }],
|
|
195
|
+
},
|
|
196
|
+
}
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
#### Available Filter Patterns
|
|
200
|
+
|
|
201
|
+
| Pattern | Example | Description |
|
|
202
|
+
| --------------------- | ----------------------------------------- | ---------------------------------- |
|
|
203
|
+
| Exact match | `'value'` | Matches exact string or number |
|
|
204
|
+
| `prefix` | `{ prefix: 'usr_' }` | Starts with |
|
|
205
|
+
| `suffix` | `{ suffix: '.com' }` | Ends with |
|
|
206
|
+
| `anything-but` | `{ 'anything-but': 'admin' }` | Matches everything except |
|
|
207
|
+
| `numeric` | `{ numeric: ['>', 100] }` | Numeric comparison |
|
|
208
|
+
| `numeric` (range) | `{ numeric: ['>=', 0, '<', 100] }` | Numeric range |
|
|
209
|
+
| `exists` | `{ exists: true }` | Field exists or does not exist |
|
|
210
|
+
| `equals-ignore-case` | `{ 'equals-ignore-case': 'active' }` | Case-insensitive string match |
|
|
211
|
+
|
|
212
|
+
### Receiving Events
|
|
213
|
+
|
|
214
|
+
Use the `@Event` parameter decorator to inject the EventBridge event payload into a handler method. The payload is automatically extracted from `$.detail`:
|
|
215
|
+
|
|
216
|
+
```typescript
|
|
217
|
+
@Rule({
|
|
218
|
+
pattern: {
|
|
219
|
+
source: 'notifications',
|
|
220
|
+
detailType: ['notification.sent'],
|
|
221
|
+
},
|
|
222
|
+
})
|
|
223
|
+
onNotification(@Event() event: any) {
|
|
224
|
+
// event contains the detail object, not the full EventBridge envelope
|
|
225
|
+
console.log(event.recipientId, event.channel);
|
|
141
226
|
}
|
|
142
227
|
```
|
|
143
228
|
|
|
144
|
-
### Event
|
|
229
|
+
### Event Buses
|
|
145
230
|
|
|
146
|
-
|
|
231
|
+
Configure one or more custom event buses when initializing `EventRuleResolver`. Each `@Rule` can target a specific bus via the `bus` option. If omitted, the default EventBridge bus is used:
|
|
147
232
|
|
|
148
|
-
|
|
233
|
+
```typescript
|
|
234
|
+
import { EventRuleResolver } from '@lafken/event/resolver';
|
|
149
235
|
|
|
236
|
+
createApp({
|
|
237
|
+
name: 'my-app',
|
|
238
|
+
resolvers: [
|
|
239
|
+
new EventRuleResolver(
|
|
240
|
+
{
|
|
241
|
+
busName: 'orders-bus',
|
|
242
|
+
extend: ({ eventBus, scope }) => {
|
|
243
|
+
// Apply additional CDKTN configuration
|
|
244
|
+
},
|
|
245
|
+
},
|
|
246
|
+
{
|
|
247
|
+
busName: 'notifications-bus',
|
|
248
|
+
}
|
|
249
|
+
),
|
|
250
|
+
],
|
|
251
|
+
});
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
Reference a specific bus from a rule:
|
|
150
255
|
|
|
151
256
|
```typescript
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
257
|
+
@Rule({
|
|
258
|
+
bus: 'orders-bus',
|
|
259
|
+
pattern: {
|
|
260
|
+
source: 'checkout',
|
|
261
|
+
detailType: ['checkout.completed'],
|
|
157
262
|
},
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
}),
|
|
161
|
-
// ...
|
|
263
|
+
})
|
|
264
|
+
onCheckout(@Event() event: any) { }
|
|
162
265
|
```
|
|
266
|
+
|
|
267
|
+
### Retry Policy
|
|
268
|
+
|
|
269
|
+
Configure how EventBridge handles failed target invocations using `retryAttempts` and `maxEventAge`:
|
|
270
|
+
|
|
271
|
+
```typescript
|
|
272
|
+
@Rule({
|
|
273
|
+
retryAttempts: 3,
|
|
274
|
+
maxEventAge: 7200,
|
|
275
|
+
pattern: {
|
|
276
|
+
source: 'billing',
|
|
277
|
+
detailType: ['invoice.generated'],
|
|
278
|
+
},
|
|
279
|
+
})
|
|
280
|
+
onInvoice(@Event() event: any) {
|
|
281
|
+
// Retries up to 3 times, discards events older than 2 hours
|
|
282
|
+
}
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
| Option | Type | Description |
|
|
286
|
+
| --------------- | -------- | ---------------------------------------------------------- |
|
|
287
|
+
| `retryAttempts` | `number` | Maximum retry attempts if the target invocation fails |
|
|
288
|
+
| `maxEventAge` | `number` | Maximum event age in seconds before the event is discarded |
|
|
@@ -1 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parameter decorator that injects the raw EventBridge event into a
|
|
3
|
+
* handler method argument.
|
|
4
|
+
*
|
|
5
|
+
* Use it on a parameter of an `@EventHandler` method so the framework
|
|
6
|
+
* passes the incoming EventBridge event payload at runtime.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```ts
|
|
10
|
+
* @EventRule({})
|
|
11
|
+
* export class OrderEvents {
|
|
12
|
+
* @EventHandler({ source: 'orders', detailType: 'order.created' })
|
|
13
|
+
* onOrderCreated(@Event() event: any) {
|
|
14
|
+
* // event contains the full EventBridge event payload
|
|
15
|
+
* }
|
|
16
|
+
* }
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
1
19
|
export declare const Event: () => (target: any, methodName: string, _number: number) => void;
|
package/lib/main/event/event.js
CHANGED
|
@@ -2,6 +2,24 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.Event = void 0;
|
|
4
4
|
const common_1 = require("@lafken/common");
|
|
5
|
+
/**
|
|
6
|
+
* Parameter decorator that injects the raw EventBridge event into a
|
|
7
|
+
* handler method argument.
|
|
8
|
+
*
|
|
9
|
+
* Use it on a parameter of an `@EventHandler` method so the framework
|
|
10
|
+
* passes the incoming EventBridge event payload at runtime.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```ts
|
|
14
|
+
* @EventRule({})
|
|
15
|
+
* export class OrderEvents {
|
|
16
|
+
* @EventHandler({ source: 'orders', detailType: 'order.created' })
|
|
17
|
+
* onOrderCreated(@Event() event: any) {
|
|
18
|
+
* // event contains the full EventBridge event payload
|
|
19
|
+
* }
|
|
20
|
+
* }
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
5
23
|
const Event = () => (target, methodName, _number) => {
|
|
6
24
|
(0, common_1.reflectArgumentMethod)(target, methodName, common_1.LambdaArgumentTypes.event);
|
|
7
25
|
};
|
package/lib/main/rule/rule.d.ts
CHANGED
|
@@ -1,4 +1,50 @@
|
|
|
1
1
|
import type { EventRuleProps } from './rule.types';
|
|
2
2
|
export declare const RESOURCE_TYPE: "EVENT";
|
|
3
|
+
/**
|
|
4
|
+
* Class decorator that registers a class as an EventBridge rule resource.
|
|
5
|
+
*
|
|
6
|
+
* The decorated class groups one or more `@Rule` handler methods that
|
|
7
|
+
* react to events published on an EventBridge bus. Each handler inside
|
|
8
|
+
* the class defines its own event pattern and integration.
|
|
9
|
+
*
|
|
10
|
+
* @param props - Optional resource configuration (e.g. a custom `name`).
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```ts
|
|
14
|
+
* @EventRule()
|
|
15
|
+
* export class OrderEvents {
|
|
16
|
+
* @Rule({ pattern: { source: 'orders', detailType: ['order.created'] } })
|
|
17
|
+
* onCreated(@Event() event) { }
|
|
18
|
+
* }
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
3
21
|
export declare const EventRule: (props?: import("@lafken/common").ResourceProps | undefined) => (constructor: Function) => void;
|
|
22
|
+
/**
|
|
23
|
+
* Method decorator that registers a handler for a specific EventBridge
|
|
24
|
+
* rule pattern.
|
|
25
|
+
*
|
|
26
|
+
* The decorated method becomes a Lambda function that is invoked when
|
|
27
|
+
* an event matching the configured pattern is published on the
|
|
28
|
+
* EventBridge bus. Supports default custom events, S3 events, and
|
|
29
|
+
* DynamoDB stream events through the `integration` option.
|
|
30
|
+
*
|
|
31
|
+
* @param props - Rule configuration including the event pattern, optional
|
|
32
|
+
* integration source, retry attempts, max event age, and bus name.
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* ```ts
|
|
36
|
+
* // Custom event
|
|
37
|
+
* @Rule({
|
|
38
|
+
* pattern: { source: 'payments', detailType: ['payment.completed'] },
|
|
39
|
+
* })
|
|
40
|
+
* onPayment(@Event() event) { }
|
|
41
|
+
*
|
|
42
|
+
* // S3 integration
|
|
43
|
+
* @Rule({
|
|
44
|
+
* integration: 's3',
|
|
45
|
+
* pattern: { detailType: ['Object Created'], detail: { bucket: { name: ['uploads'] } } },
|
|
46
|
+
* })
|
|
47
|
+
* onUpload(@Event() event) { }
|
|
48
|
+
* ```
|
|
49
|
+
*/
|
|
4
50
|
export declare const Rule: (props: EventRuleProps) => (target: any, methodName: string, descriptor: PropertyDescriptor) => any;
|
package/lib/main/rule/rule.js
CHANGED
|
@@ -3,10 +3,56 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.Rule = exports.EventRule = exports.RESOURCE_TYPE = void 0;
|
|
4
4
|
const common_1 = require("@lafken/common");
|
|
5
5
|
exports.RESOURCE_TYPE = 'EVENT';
|
|
6
|
+
/**
|
|
7
|
+
* Class decorator that registers a class as an EventBridge rule resource.
|
|
8
|
+
*
|
|
9
|
+
* The decorated class groups one or more `@Rule` handler methods that
|
|
10
|
+
* react to events published on an EventBridge bus. Each handler inside
|
|
11
|
+
* the class defines its own event pattern and integration.
|
|
12
|
+
*
|
|
13
|
+
* @param props - Optional resource configuration (e.g. a custom `name`).
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```ts
|
|
17
|
+
* @EventRule()
|
|
18
|
+
* export class OrderEvents {
|
|
19
|
+
* @Rule({ pattern: { source: 'orders', detailType: ['order.created'] } })
|
|
20
|
+
* onCreated(@Event() event) { }
|
|
21
|
+
* }
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
6
24
|
exports.EventRule = (0, common_1.createResourceDecorator)({
|
|
7
25
|
type: exports.RESOURCE_TYPE,
|
|
8
26
|
callerFileIndex: 5,
|
|
9
27
|
});
|
|
28
|
+
/**
|
|
29
|
+
* Method decorator that registers a handler for a specific EventBridge
|
|
30
|
+
* rule pattern.
|
|
31
|
+
*
|
|
32
|
+
* The decorated method becomes a Lambda function that is invoked when
|
|
33
|
+
* an event matching the configured pattern is published on the
|
|
34
|
+
* EventBridge bus. Supports default custom events, S3 events, and
|
|
35
|
+
* DynamoDB stream events through the `integration` option.
|
|
36
|
+
*
|
|
37
|
+
* @param props - Rule configuration including the event pattern, optional
|
|
38
|
+
* integration source, retry attempts, max event age, and bus name.
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* ```ts
|
|
42
|
+
* // Custom event
|
|
43
|
+
* @Rule({
|
|
44
|
+
* pattern: { source: 'payments', detailType: ['payment.completed'] },
|
|
45
|
+
* })
|
|
46
|
+
* onPayment(@Event() event) { }
|
|
47
|
+
*
|
|
48
|
+
* // S3 integration
|
|
49
|
+
* @Rule({
|
|
50
|
+
* integration: 's3',
|
|
51
|
+
* pattern: { detailType: ['Object Created'], detail: { bucket: { name: ['uploads'] } } },
|
|
52
|
+
* })
|
|
53
|
+
* onUpload(@Event() event) { }
|
|
54
|
+
* ```
|
|
55
|
+
*/
|
|
10
56
|
const Rule = (props) => (0, common_1.createLambdaDecorator)({
|
|
11
57
|
getLambdaMetadata: (props, methodName) => ({
|
|
12
58
|
...props,
|
package/lib/resolver/resolver.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.EventRuleResolver = void 0;
|
|
4
|
-
const cloudwatch_event_bus_1 = require("@
|
|
5
|
-
const data_aws_cloudwatch_event_bus_1 = require("@
|
|
4
|
+
const cloudwatch_event_bus_1 = require("@cdktn/provider-aws/lib/cloudwatch-event-bus");
|
|
5
|
+
const data_aws_cloudwatch_event_bus_1 = require("@cdktn/provider-aws/lib/data-aws-cloudwatch-event-bus");
|
|
6
6
|
const common_1 = require("@lafken/common");
|
|
7
7
|
const resolver_1 = require("@lafken/resolver");
|
|
8
8
|
const main_1 = require("../main");
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { CloudwatchEventBus } from '@
|
|
1
|
+
import type { CloudwatchEventBus } from '@cdktn/provider-aws/lib/cloudwatch-event-bus';
|
|
2
2
|
import type { EventBusNames } from '@lafken/common';
|
|
3
3
|
import type { AppStack } from '@lafken/resolver';
|
|
4
4
|
interface ExtendProps {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CloudwatchEventRule } from '@
|
|
1
|
+
import { CloudwatchEventRule } from '@cdktn/provider-aws/lib/cloudwatch-event-rule';
|
|
2
2
|
import { type AppModule } from '@lafken/resolver';
|
|
3
3
|
import type { RuleProps } from './rule.types';
|
|
4
4
|
declare const Rule_base: (new (...args: any[]) => {
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.Rule = void 0;
|
|
4
|
-
const cloudwatch_event_rule_1 = require("@
|
|
5
|
-
const cloudwatch_event_target_1 = require("@
|
|
4
|
+
const cloudwatch_event_rule_1 = require("@cdktn/provider-aws/lib/cloudwatch-event-rule");
|
|
5
|
+
const cloudwatch_event_target_1 = require("@cdktn/provider-aws/lib/cloudwatch-event-target");
|
|
6
6
|
const resolver_1 = require("@lafken/resolver");
|
|
7
|
-
const
|
|
7
|
+
const cdktn_1 = require("cdktn");
|
|
8
8
|
class Rule extends resolver_1.lafkenResource.make(cloudwatch_event_rule_1.CloudwatchEventRule) {
|
|
9
9
|
props;
|
|
10
10
|
constructor(scope, id, props) {
|
|
@@ -12,7 +12,7 @@ class Rule extends resolver_1.lafkenResource.make(cloudwatch_event_rule_1.Cloudw
|
|
|
12
12
|
super(scope, `${id}-rule`, {
|
|
13
13
|
name: id,
|
|
14
14
|
eventBusName: bus.name,
|
|
15
|
-
eventPattern:
|
|
15
|
+
eventPattern: cdktn_1.Fn.jsonencode(Rule.getEvent(handler)),
|
|
16
16
|
});
|
|
17
17
|
this.props = props;
|
|
18
18
|
this.isGlobal(scope.id, id);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { CloudwatchEventBus } from '@
|
|
1
|
+
import type { CloudwatchEventBus } from '@cdktn/provider-aws/lib/cloudwatch-event-bus';
|
|
2
2
|
import type { ResourceMetadata } from '@lafken/common';
|
|
3
3
|
import type { EventRuleMetadata } from '../../main';
|
|
4
4
|
export interface RuleProps {
|
package/package.json
CHANGED
|
@@ -1,16 +1,27 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lafken/event",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"private": false,
|
|
5
|
-
"description": "
|
|
5
|
+
"description": "Define EventBridge event listeners using TypeScript decorators - serverless event-driven infrastructure",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"aws",
|
|
8
8
|
"eventbridge",
|
|
9
9
|
"event",
|
|
10
|
+
"event-driven",
|
|
10
11
|
"serverless",
|
|
12
|
+
"typescript",
|
|
13
|
+
"decorators",
|
|
11
14
|
"lafken"
|
|
12
15
|
],
|
|
16
|
+
"homepage": "https://github.com/Hero64/lafken#readme",
|
|
17
|
+
"bugs": "https://github.com/Hero64/lafken/issues",
|
|
18
|
+
"repository": {
|
|
19
|
+
"type": "git",
|
|
20
|
+
"url": "https://github.com/Hero64/lafken",
|
|
21
|
+
"directory": "packages/event"
|
|
22
|
+
},
|
|
13
23
|
"license": "MIT",
|
|
24
|
+
"author": "Aníbal Jorquera",
|
|
14
25
|
"exports": {
|
|
15
26
|
"./main": {
|
|
16
27
|
"import": "./lib/main/index.js",
|
|
@@ -37,28 +48,38 @@
|
|
|
37
48
|
"lib"
|
|
38
49
|
],
|
|
39
50
|
"dependencies": {
|
|
40
|
-
"
|
|
41
|
-
"
|
|
42
|
-
"constructs": "10.4.4",
|
|
43
|
-
"reflect-metadata": "0.2.2",
|
|
44
|
-
"@lafken/common": "0.6.4",
|
|
45
|
-
"@lafken/resolver": "0.6.4"
|
|
51
|
+
"reflect-metadata": "^0.2.2",
|
|
52
|
+
"@lafken/resolver": "0.8.0"
|
|
46
53
|
},
|
|
47
54
|
"devDependencies": {
|
|
48
|
-
"@
|
|
49
|
-
"@
|
|
50
|
-
"
|
|
51
|
-
"
|
|
52
|
-
"
|
|
55
|
+
"@cdktn/provider-aws": "^23.0.0",
|
|
56
|
+
"@swc/core": "^1.15.11",
|
|
57
|
+
"@swc/helpers": "^0.5.18",
|
|
58
|
+
"@vitest/runner": "^4.0.18",
|
|
59
|
+
"cdktn": "^0.22.0",
|
|
60
|
+
"cdktn-vitest": "^1.0.0",
|
|
61
|
+
"constructs": "^10.4.5",
|
|
62
|
+
"unplugin-swc": "^1.5.9",
|
|
63
|
+
"vitest": "^4.0.18",
|
|
64
|
+
"@lafken/common": "0.8.0"
|
|
65
|
+
},
|
|
66
|
+
"peerDependencies": {
|
|
67
|
+
"@cdktn/provider-aws": "^23.0.0",
|
|
68
|
+
"@lafken/common": "^0.7.0",
|
|
69
|
+
"cdktn": "^0.22.0",
|
|
70
|
+
"constructs": "^10.4.5"
|
|
71
|
+
},
|
|
72
|
+
"engines": {
|
|
73
|
+
"node": ">=20.19"
|
|
53
74
|
},
|
|
54
75
|
"publishConfig": {
|
|
55
76
|
"access": "public"
|
|
56
77
|
},
|
|
57
78
|
"scripts": {
|
|
58
79
|
"build": "pnpm clean && tsc -p ./tsconfig.build.json",
|
|
80
|
+
"check-types": "tsc --noEmit -p ./tsconfig.build.json",
|
|
59
81
|
"clean": "rm -rf ./lib",
|
|
60
82
|
"dev": "tsc -w",
|
|
61
|
-
"test": "
|
|
62
|
-
"test:coverage": "jest --coverage"
|
|
83
|
+
"test": "vitest"
|
|
63
84
|
}
|
|
64
85
|
}
|