@lafken/event 0.6.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/LICENCE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Aníbal Emilio Jorquera Cornejo
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,162 @@
1
+ # @lafken/event
2
+
3
+ `@lafken/event` helps you create listeners for EventBridge events and trigger Lambda functions to process those events. It provides decorators that simplify configuring event listeners—whether for custom events or built-in sources like S3 and DynamoDB.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @lafken/event
9
+ ```
10
+
11
+ ## Configuration
12
+
13
+ Add the EventRuleResolver from the @lafken/event/resolver library.
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.
15
+
16
+ ```typescript
17
+ import { ApiResolver } from '@lafken/event/resolver';
18
+
19
+ createApp({
20
+ name: 'awesome-app',
21
+ resolvers: [
22
+ new EventRuleResolver({
23
+ busName: 'awesome-event-bus',
24
+ extend: ({ eventBus }) => {
25
+ // ... extend the event bus
26
+ },
27
+ }),
28
+ ],
29
+ ...
30
+ });
31
+ ```
32
+
33
+ This setup allows you to customize how events are routed and processed within your application.
34
+
35
+ Next, you need to configure the module by importing the class resources decorated with the @EventRule decorator. These classes must contain methods decorated with @Rule, which will create the event listener and attach the corresponding Lambda function for execution.
36
+
37
+ ```typescript
38
+ @EventRule({
39
+ minify: false,
40
+ })
41
+ export class GreetingEvent {
42
+ @Rule({
43
+ bus: 'awesome-event-bus',
44
+ pattern: {
45
+ source: 'simple-source',
46
+ },
47
+ })
48
+ simpleEvent(@Event() e: any) {
49
+ // ...
50
+ }
51
+ }
52
+
53
+ const greetingModule = createModule({
54
+ name: 'greeting',
55
+ resources: [
56
+ GreetingEvent
57
+ ]
58
+ });
59
+ ```
60
+
61
+ ## Features
62
+
63
+ ### Receiving and Filtering Events
64
+ The @Rule decorator allows you to define an event pattern by specifying the event source and applying filters on detail and detailType.
65
+
66
+ ```typescript
67
+ @Rule({
68
+ pattern: {
69
+ source: 'simple-source',
70
+ detail: {
71
+ name: ['foo', 'bar'],
72
+ },
73
+ detailType: ['CREATE', 'UPDATE'],
74
+ },
75
+ })
76
+ // ...
77
+ ```
78
+
79
+ ### Receiving Events
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.
81
+
82
+ ```typescript
83
+ @Rule(/* ... */)
84
+ sayHelloFromEvent(@Event() event: any) {
85
+ console.log('simple source', event);
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.
91
+
92
+ To enable S3 integration within an event rule, set the integration property to 's3' and define a pattern that matches the desired S3 event structure.
93
+
94
+ ```typescript
95
+ @Rule({
96
+ integration: 's3',
97
+ pattern: {
98
+ detailType: ['Object Created'],
99
+ detail: {
100
+ bucket: {
101
+ name: ['lafken-example-documents'],
102
+ },
103
+ object: {
104
+ key: [
105
+ {
106
+ prefix: 'test.json',
107
+ },
108
+ ],
109
+ },
110
+ },
111
+ },
112
+ })
113
+ s3(@Event() event: any) {
114
+ // Handler logic
115
+ }
116
+ ```
117
+
118
+ ### Dynamo Integration
119
+ Event rules can also consume and process events emitted by Amazon DynamoDB Streams.
120
+ To use this integration, you must first enable DynamoDB Streams on the target table. Once enabled, DynamoDB will emit change records (INSERT, MODIFY, REMOVE), which can be routed through EventBridge and processed by your rule.
121
+
122
+ After the stream is configured, you can define a rule with the integration: 'dynamodb' option and provide a pattern to filter the specific DynamoDB events you want to handle.
123
+
124
+ ```typescript
125
+ @Rule({
126
+ integration: 'dynamodb',
127
+ pattern: {
128
+ source: 'clients',
129
+ detail: {
130
+ eventName: ['INSERT', 'MODIFY'],
131
+ keys: {
132
+ email: {
133
+ prefix: 'awesome',
134
+ },
135
+ },
136
+ },
137
+ },
138
+ })
139
+ dynamo(@Event() e: any) {
140
+ // ...
141
+ }
142
+ ```
143
+
144
+ ### Event bus
145
+
146
+ It is possible to configure multiple Event Buses when initializing the EventRuleResolver. Each event bus can then be referenced from individual rules by specifying its name in the bus property of the @Rule decorator.
147
+
148
+ If no event bus is explicitly configured for a rule, the default EventBridge bus will be used automatically.
149
+
150
+
151
+ ```typescript
152
+ //...
153
+ new EventRuleResolver({
154
+ busName: 'awesome-event-bus',
155
+ extend: ({ eventBus }) => {
156
+ // ... extend the event bus
157
+ },
158
+ }, {
159
+ busName: 'another-event-bus'
160
+ }),
161
+ // ...
162
+ ```
package/lib/index.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ export * from './main';
2
+ export * from './resolver';
package/lib/index.js ADDED
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./main"), exports);
18
+ __exportStar(require("./resolver"), exports);
@@ -0,0 +1 @@
1
+ export declare const Event: () => (target: any, methodName: string, _number: number) => void;
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Event = void 0;
4
+ const common_1 = require("@lafken/common");
5
+ const Event = () => (target, methodName, _number) => {
6
+ (0, common_1.reflectArgumentMethod)(target, methodName, common_1.LambdaArgumentTypes.event);
7
+ };
8
+ exports.Event = Event;
@@ -0,0 +1,2 @@
1
+ export * from './event/event';
2
+ export * from './rule';
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./event/event"), exports);
18
+ __exportStar(require("./rule"), exports);
@@ -0,0 +1,2 @@
1
+ export * from './rule';
2
+ export * from './rule.types';
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./rule"), exports);
18
+ __exportStar(require("./rule.types"), exports);
@@ -0,0 +1,4 @@
1
+ import type { EventRuleProps } from './rule.types';
2
+ export declare const RESOURCE_TYPE: "EVENT";
3
+ export declare const EventRule: (props?: import("@lafken/common").ResourceProps | undefined) => (constructor: Function) => void;
4
+ export declare const Rule: (props: EventRuleProps) => (target: any, methodName: string, descriptor: PropertyDescriptor) => any;
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Rule = exports.EventRule = exports.RESOURCE_TYPE = void 0;
4
+ const common_1 = require("@lafken/common");
5
+ exports.RESOURCE_TYPE = 'EVENT';
6
+ exports.EventRule = (0, common_1.createResourceDecorator)({
7
+ type: exports.RESOURCE_TYPE,
8
+ callerFileIndex: 5,
9
+ });
10
+ const Rule = (props) => (0, common_1.createLambdaDecorator)({
11
+ getLambdaMetadata: (props, methodName) => ({
12
+ ...props,
13
+ name: methodName,
14
+ eventType: 'rule',
15
+ }),
16
+ })(props);
17
+ exports.Rule = Rule;
@@ -0,0 +1,211 @@
1
+ import type { BucketNames, DynamoTableNames, EventBusNames, LambdaMetadata } from '@lafken/common';
2
+ export interface EventRuleBaseProps {
3
+ /**
4
+ * Maximum event age.
5
+ *
6
+ * Specifies the maximum age of an event that can be sent to the rule's targets.
7
+ * Events older than this duration will be discarded.
8
+ */
9
+ maxEventAge?: number;
10
+ /**
11
+ * Retry attempts for failed events.
12
+ *
13
+ * Specifies the maximum number of times EventBridge will retry sending
14
+ * an event to the target if the initial attempt fails.
15
+ */
16
+ retryAttempts?: number;
17
+ /**
18
+ * Event bus name.
19
+ *
20
+ * Specifies the EventBridge bus where the rule will be created.
21
+ * If not provided, the default event bus is used.
22
+ */
23
+ bus?: EventBusNames;
24
+ }
25
+ export type S3DetailType = 'Object Created' | 'Object Deleted';
26
+ export type S3ObjectKey = {
27
+ prefix?: string;
28
+ suffix?: string;
29
+ };
30
+ export interface S3Detail {
31
+ bucket?: {
32
+ name: BucketNames[];
33
+ };
34
+ object?: {
35
+ key?: (S3ObjectKey | string)[];
36
+ };
37
+ }
38
+ export interface EventDefaultRuleProps extends EventRuleBaseProps {
39
+ /**
40
+ * Integration source for the EventBridge rule.
41
+ *
42
+ * Specifies the AWS service that will emit events for this rule.
43
+ * Common examples include:
44
+ * - `'dynamodb'` – captures events from a DynamoDB table.
45
+ * - `'s3'` – captures events from an S3 bucket.
46
+ */
47
+ integration?: never;
48
+ /**
49
+ * Event pattern for the EventBridge rule.
50
+ *
51
+ * Defines the filtering criteria that determine which events
52
+ * trigger the rule. Events are matched against the specified
53
+ * pattern fields.
54
+ * @example
55
+ * {
56
+ * pattern: {
57
+ * source: "<event_source>",
58
+ * detailType: ['foo'],
59
+ * detail: {
60
+ * foo: 'bar'
61
+ * }
62
+ * }
63
+ * }
64
+ */
65
+ pattern: {
66
+ /**
67
+ * Event source.
68
+ *
69
+ * Specifies the AWS service or custom source that emits the events
70
+ * to be captured by this EventBridge rule.
71
+ */
72
+ source: string;
73
+ /**
74
+ * Event types to match.
75
+ *
76
+ * Optional array of event types (detailType) that should trigger the rule.
77
+ * If not specified, all event types from the source are captured.
78
+ */
79
+ detailType?: string[];
80
+ /**
81
+ * Additional filtering criteria on the event payload.
82
+ *
83
+ * Optional object specifying conditions on event attributes to further
84
+ * filter which events trigger the rule.
85
+ */
86
+ detail?: any;
87
+ };
88
+ }
89
+ export interface EventS3RuleProps extends EventRuleBaseProps {
90
+ /**
91
+ * Integration source for the EventBridge rule.
92
+ *
93
+ * Specifies the AWS service that will emit events for this rule.
94
+ * Common examples include:
95
+ * - `'dynamodb'` – captures events from a DynamoDB table.
96
+ * - `'s3'` – captures events from an S3 bucket.
97
+ */
98
+ integration: 's3';
99
+ /**
100
+ * Event pattern for the EventBridge rule.
101
+ *
102
+ * Defines the filtering criteria that determine which events
103
+ * trigger the rule. Events are matched against the specified
104
+ * pattern fields.
105
+ *
106
+ * @example
107
+ * {
108
+ * pattern: {
109
+ * detailType: ['Object Created'],
110
+ * detail: {
111
+ * bucket: {
112
+ * name: 'bucket_name'
113
+ * }
114
+ * }
115
+ * }
116
+ * }
117
+ */
118
+ pattern: {
119
+ /**
120
+ * Event types to match.
121
+ *
122
+ * Optional array of event types (detailType) that should trigger the rule.
123
+ * If not specified, all event types from the source are captured.
124
+ */
125
+ detailType: S3DetailType[];
126
+ /**
127
+ * Additional filtering criteria on the event payload.
128
+ *
129
+ * Optional object specifying conditions on event attributes to further
130
+ * filter which events trigger the rule.
131
+ */
132
+ detail: S3Detail;
133
+ };
134
+ }
135
+ type PrefixPattern = {
136
+ prefix: string;
137
+ };
138
+ type SuffixPattern = {
139
+ suffix: string;
140
+ };
141
+ type AnythingButPattern = {
142
+ 'anything-but': string | string[];
143
+ };
144
+ type NumericPattern = {
145
+ numeric: ['=' | '>' | '>=' | '<' | '<=', number] | ['>' | '>=', number, '<' | '<=', number];
146
+ };
147
+ type ExistsPattern = {
148
+ exists: boolean;
149
+ };
150
+ type EqualsIgnoreCasePattern = {
151
+ 'equals-ignore-case': string;
152
+ };
153
+ export type EventBridgePattern = string | number | boolean | PrefixPattern | SuffixPattern | AnythingButPattern | NumericPattern | ExistsPattern | EqualsIgnoreCasePattern;
154
+ export type DynamoAttributeFilter = EventBridgePattern | EventBridgePattern[];
155
+ export type DynamoAttributeFilters = Record<string, DynamoAttributeFilter>;
156
+ interface DynamoDetail {
157
+ eventName?: ('INSERT' | 'MODIFY' | 'REMOVE')[];
158
+ keys?: DynamoAttributeFilters;
159
+ newImage?: DynamoAttributeFilters;
160
+ oldImage?: DynamoAttributeFilters;
161
+ }
162
+ export interface DynamoRuleProps extends EventRuleBaseProps {
163
+ /**
164
+ * Integration source for the EventBridge rule.
165
+ *
166
+ * Specifies the AWS service that will emit events for this rule.
167
+ * Common examples include:
168
+ * - `'dynamodb'` – captures events from a DynamoDB table.
169
+ * - `'s3'` – captures events from an S3 bucket.
170
+ */
171
+ integration: 'dynamodb';
172
+ /**
173
+ * Event pattern for the EventBridge rule.
174
+ *
175
+ * Defines the filtering criteria that determine which events
176
+ * trigger the rule. Events are matched against the specified
177
+ * pattern fields.
178
+ *
179
+ * @example
180
+ * {
181
+ * pattern: {
182
+ * source: 'dynamo_table_name',
183
+ * detail: {
184
+ * eventname: ['INSERT'],
185
+ * keys: {
186
+ * PK: ['a', 'b']
187
+ * }
188
+ * }
189
+ * }
190
+ * }
191
+ */
192
+ pattern: {
193
+ /**
194
+ * Event source.
195
+ *
196
+ * Specifies the AWS service or custom source that emits the events
197
+ * to be captured by this EventBridge rule.
198
+ */
199
+ source: DynamoTableNames;
200
+ /**
201
+ * Additional filtering criteria on the event payload.
202
+ *
203
+ * Optional object specifying conditions on event attributes to further
204
+ * filter which events trigger the rule.
205
+ */
206
+ detail?: DynamoDetail;
207
+ };
208
+ }
209
+ export type EventRuleProps = EventDefaultRuleProps | EventS3RuleProps | DynamoRuleProps;
210
+ export type EventRuleMetadata = LambdaMetadata & EventRuleProps;
211
+ export {};
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1 @@
1
+ export * from './resolver';
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./resolver"), exports);
@@ -0,0 +1,11 @@
1
+ import { type ClassResource } from '@lafken/common';
2
+ import { type AppModule, type AppStack, type ResolverType } from '@lafken/resolver';
3
+ import type { EventRuleResolverProps } from './resolver.types';
4
+ export declare class EventRuleResolver implements ResolverType {
5
+ type: "EVENT";
6
+ private eventBuses;
7
+ private props;
8
+ constructor(...props: EventRuleResolverProps[]);
9
+ beforeCreate(scope: AppStack): Promise<void>;
10
+ create(module: AppModule, resource: ClassResource): void;
11
+ }
@@ -0,0 +1,54 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.EventRuleResolver = void 0;
4
+ const cloudwatch_event_bus_1 = require("@cdktf/provider-aws/lib/cloudwatch-event-bus");
5
+ const data_aws_cloudwatch_event_bus_1 = require("@cdktf/provider-aws/lib/data-aws-cloudwatch-event-bus");
6
+ const common_1 = require("@lafken/common");
7
+ const resolver_1 = require("@lafken/resolver");
8
+ const main_1 = require("../main");
9
+ const rule_1 = require("./rule/rule");
10
+ class EventRuleResolver {
11
+ type = main_1.RESOURCE_TYPE;
12
+ eventBuses = {};
13
+ props = [];
14
+ constructor(...props) {
15
+ if (props) {
16
+ this.props = props;
17
+ }
18
+ }
19
+ async beforeCreate(scope) {
20
+ const defaultBus = new data_aws_cloudwatch_event_bus_1.DataAwsCloudwatchEventBus(scope, 'EventDefaultBus', {
21
+ name: 'default',
22
+ });
23
+ this.eventBuses.default = defaultBus;
24
+ for (const eventBusProps of this.props) {
25
+ if (eventBusProps.busName === 'default') {
26
+ throw new Error('Event bus default already exist');
27
+ }
28
+ this.eventBuses[eventBusProps.busName] = new cloudwatch_event_bus_1.CloudwatchEventBus(scope, `${eventBusProps.busName}-bus`, {
29
+ name: eventBusProps.busName,
30
+ });
31
+ }
32
+ }
33
+ create(module, resource) {
34
+ const metadata = (0, common_1.getResourceMetadata)(resource);
35
+ const handlers = (0, common_1.getResourceHandlerMetadata)(resource);
36
+ resolver_1.lambdaAssets.initializeMetadata({
37
+ foldername: metadata.foldername,
38
+ filename: metadata.filename,
39
+ minify: metadata.minify,
40
+ className: metadata.originalName,
41
+ methods: handlers.map((handler) => handler.name),
42
+ });
43
+ for (const handler of handlers) {
44
+ const id = `${handler.name}-${metadata.name}`;
45
+ const bus = this.eventBuses[handler.bus || 'default'];
46
+ new rule_1.Rule(module, id, {
47
+ bus,
48
+ handler,
49
+ resourceMetadata: metadata,
50
+ });
51
+ }
52
+ }
53
+ }
54
+ exports.EventRuleResolver = EventRuleResolver;
@@ -0,0 +1,12 @@
1
+ import type { CloudwatchEventBus } from '@cdktf/provider-aws/lib/cloudwatch-event-bus';
2
+ import type { EventBusNames } from '@lafken/common';
3
+ import type { AppStack } from '@lafken/resolver';
4
+ interface ExtendProps {
5
+ scope: AppStack;
6
+ eventBus: CloudwatchEventBus;
7
+ }
8
+ export interface EventRuleResolverProps {
9
+ busName: EventBusNames;
10
+ extend?: (props: ExtendProps) => void;
11
+ }
12
+ export {};
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,18 @@
1
+ import { CloudwatchEventRule } from '@cdktf/provider-aws/lib/cloudwatch-event-rule';
2
+ import { type AppModule } from '@lafken/resolver';
3
+ import type { RuleProps } from './rule.types';
4
+ declare const Rule_base: (new (...args: any[]) => {
5
+ isGlobal(module: import("@lafken/common").ModuleGlobalReferenceNames | (string & {}), id: string): void;
6
+ isDependent(resolveDependency: () => void): void;
7
+ readonly node: import("constructs").Node;
8
+ toString(): string;
9
+ }) & typeof CloudwatchEventRule;
10
+ export declare class Rule extends Rule_base {
11
+ private props;
12
+ constructor(scope: AppModule, id: string, props: RuleProps);
13
+ private addEventTarget;
14
+ private static getEvent;
15
+ private static inferDynamoDBType;
16
+ private static transformAttributes;
17
+ }
18
+ export {};
@@ -0,0 +1,125 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Rule = void 0;
4
+ const cloudwatch_event_rule_1 = require("@cdktf/provider-aws/lib/cloudwatch-event-rule");
5
+ const cloudwatch_event_target_1 = require("@cdktf/provider-aws/lib/cloudwatch-event-target");
6
+ const resolver_1 = require("@lafken/resolver");
7
+ const cdktf_1 = require("cdktf");
8
+ class Rule extends resolver_1.lafkenResource.make(cloudwatch_event_rule_1.CloudwatchEventRule) {
9
+ props;
10
+ constructor(scope, id, props) {
11
+ const { handler, bus } = props;
12
+ super(scope, `${id}-rule`, {
13
+ name: id,
14
+ eventBusName: bus.name,
15
+ eventPattern: cdktf_1.Fn.jsonencode(Rule.getEvent(handler)),
16
+ });
17
+ this.props = props;
18
+ this.isGlobal(scope.id, id);
19
+ this.addEventTarget(id);
20
+ }
21
+ addEventTarget(id) {
22
+ const { resourceMetadata, handler } = this.props;
23
+ const lambdaHandler = new resolver_1.LambdaHandler(this, `${handler.name}-${resourceMetadata.name}`, {
24
+ ...handler,
25
+ originalName: resourceMetadata.originalName,
26
+ filename: resourceMetadata.filename,
27
+ foldername: resourceMetadata.foldername,
28
+ suffix: 'event',
29
+ principal: 'events.amazonaws.com',
30
+ });
31
+ new cloudwatch_event_target_1.CloudwatchEventTarget(this, `${id}-event-target`, {
32
+ rule: this.name,
33
+ arn: lambdaHandler.arn,
34
+ retryPolicy: {
35
+ maximumRetryAttempts: handler.retryAttempts,
36
+ maximumEventAgeInSeconds: handler.maxEventAge,
37
+ },
38
+ inputPath: '$.detail',
39
+ });
40
+ }
41
+ static getEvent(handler) {
42
+ if (!handler.integration) {
43
+ return {
44
+ source: [handler.pattern.source],
45
+ detail: handler.pattern.detail,
46
+ 'detail-type': handler.pattern.detailType,
47
+ };
48
+ }
49
+ switch (handler.integration) {
50
+ case 's3': {
51
+ return {
52
+ source: ['aws.s3'],
53
+ 'detail-type': handler.pattern.detailType,
54
+ detail: handler.pattern.detail,
55
+ };
56
+ }
57
+ case 'dynamodb': {
58
+ const dynamoDetail = {
59
+ ...(handler.pattern.detail?.keys
60
+ ? {
61
+ Keys: Rule.transformAttributes(handler.pattern.detail?.keys),
62
+ }
63
+ : {}),
64
+ ...(handler.pattern.detail?.newImage
65
+ ? {
66
+ NewImage: Rule.transformAttributes(handler.pattern.detail?.newImage),
67
+ }
68
+ : {}),
69
+ ...(handler.pattern.detail?.oldImage
70
+ ? {
71
+ OldImage: Rule.transformAttributes(handler.pattern.detail?.oldImage),
72
+ }
73
+ : {}),
74
+ };
75
+ return {
76
+ source: [`dynamodb.${handler.pattern.source}`],
77
+ 'detail-type': ['db:stream'],
78
+ ...(Object.keys(dynamoDetail).length > 0 || handler.pattern.detail?.eventName
79
+ ? {
80
+ detail: {
81
+ ...(handler.pattern.detail?.eventName
82
+ ? {
83
+ eventName: handler.pattern.detail?.eventName,
84
+ }
85
+ : {}),
86
+ dynamodb: dynamoDetail,
87
+ },
88
+ }
89
+ : {}),
90
+ };
91
+ }
92
+ default:
93
+ throw new Error('Unsupported integration type');
94
+ }
95
+ }
96
+ static inferDynamoDBType(value) {
97
+ if (typeof value === 'string')
98
+ return 'S';
99
+ if (typeof value === 'number')
100
+ return 'N';
101
+ if (typeof value === 'boolean')
102
+ return 'BOOL';
103
+ if (typeof value === 'object') {
104
+ if ('numeric' in value)
105
+ return 'N';
106
+ if ('prefix' in value || 'suffix' in value || 'equals-ignore-case' in value)
107
+ return 'S';
108
+ }
109
+ return 'S';
110
+ }
111
+ static transformAttributes(attrs) {
112
+ if (!attrs)
113
+ return undefined;
114
+ const transformed = {};
115
+ for (const [key, value] of Object.entries(attrs)) {
116
+ const values = Array.isArray(value) ? value : [value];
117
+ const type = Rule.inferDynamoDBType(values[0]);
118
+ transformed[key] = {
119
+ [type]: values,
120
+ };
121
+ }
122
+ return transformed;
123
+ }
124
+ }
125
+ exports.Rule = Rule;
@@ -0,0 +1,8 @@
1
+ import type { CloudwatchEventBus } from '@cdktf/provider-aws/lib/cloudwatch-event-bus';
2
+ import type { ResourceMetadata } from '@lafken/common';
3
+ import type { EventRuleMetadata } from '../../main';
4
+ export interface RuleProps {
5
+ resourceMetadata: ResourceMetadata;
6
+ handler: EventRuleMetadata;
7
+ bus: CloudwatchEventBus;
8
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
package/package.json ADDED
@@ -0,0 +1,56 @@
1
+ {
2
+ "name": "@lafken/event",
3
+ "version": "0.6.0",
4
+ "private": false,
5
+ "license": "MIT",
6
+ "exports": {
7
+ "./main": {
8
+ "import": "./lib/main/index.js",
9
+ "types": "./lib/main/index.d.ts",
10
+ "require": "./lib/main/index.js"
11
+ },
12
+ "./resolver": {
13
+ "import": "./lib/resolver/index.js",
14
+ "types": "./lib/resolver/index.d.ts",
15
+ "require": "./lib/resolver/index.js"
16
+ }
17
+ },
18
+ "typesVersions": {
19
+ "*": {
20
+ "main": [
21
+ "./lib/main/index.d.ts"
22
+ ],
23
+ "resolver": [
24
+ "./lib/resolver/index.d.ts"
25
+ ]
26
+ }
27
+ },
28
+ "files": [
29
+ "lib"
30
+ ],
31
+ "dependencies": {
32
+ "@cdktf/provider-aws": "21.22.0",
33
+ "cdktf": "0.21.0",
34
+ "constructs": "10.4.4",
35
+ "reflect-metadata": "0.2.2",
36
+ "@lafken/common": "0.6.0",
37
+ "@lafken/resolver": "0.6.0"
38
+ },
39
+ "devDependencies": {
40
+ "@jest/types": "^30.2.0",
41
+ "@types/jest": "30.0.0",
42
+ "jest": "30.2.0",
43
+ "ts-jest": "29.4.6",
44
+ "ts-node": "10.9.2"
45
+ },
46
+ "publishConfig": {
47
+ "access": "public"
48
+ },
49
+ "scripts": {
50
+ "build": "pnpm clean && tsc -p ./tsconfig.build.json",
51
+ "clean": "rm -rf ./lib",
52
+ "dev": "tsc -w",
53
+ "test": "jest",
54
+ "test:coverage": "jest --coverage"
55
+ }
56
+ }