@cloudnux/cli 0.19.0 → 0.21.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.
@@ -0,0 +1,33 @@
1
+ # SNS Trigger Module - main.tf
2
+
3
+ data "aws_sns_topic" "this" {
4
+ for_each = var.event_sources
5
+ name = each.value.topic_name
6
+ }
7
+
8
+ resource "aws_sns_topic_subscription" "this" {
9
+ for_each = var.event_sources
10
+
11
+ topic_arn = data.aws_sns_topic.this[each.key].arn
12
+ protocol = "lambda"
13
+ endpoint = var.lambda_arn
14
+
15
+ filter_policy = try(each.value.filter_policy, null)
16
+ filter_policy_scope = try(each.value.filter_policy, null) != null ? try(each.value.filter_policy_scope, "MessageAttributes") : null
17
+
18
+ lifecycle {
19
+ create_before_destroy = true
20
+ }
21
+ }
22
+
23
+ # SNS (unlike SQS event source mappings) requires an explicit resource-based
24
+ # permission for the topic to invoke the Lambda function.
25
+ resource "aws_lambda_permission" "allow_sns" {
26
+ for_each = var.event_sources
27
+
28
+ statement_id = "AllowExecutionFromSNS-${each.key}"
29
+ action = "lambda:InvokeFunction"
30
+ function_name = var.lambda_name
31
+ principal = "sns.amazonaws.com"
32
+ source_arn = data.aws_sns_topic.this[each.key].arn
33
+ }
@@ -0,0 +1,18 @@
1
+ variable "event_sources" {
2
+ description = "Map of SNS event source configurations"
3
+ type = map(object({
4
+ topic_name = string
5
+ filter_policy = optional(string)
6
+ filter_policy_scope = optional(string, "MessageAttributes")
7
+ }))
8
+ }
9
+
10
+ variable "lambda_name" {
11
+ description = "Name of the Lambda function"
12
+ type = string
13
+ }
14
+
15
+ variable "lambda_arn" {
16
+ description = "ARN of the Lambda function"
17
+ type = string
18
+ }
package/dist/cli.mjs CHANGED
@@ -2954,6 +2954,7 @@ var transformTriggerTemplate = {
2954
2954
  http: "../.deploy/aws/http",
2955
2955
  scheduler: "../.deploy/aws/scheduler",
2956
2956
  sqs: "../.deploy/aws/sqs",
2957
+ sns: "../.deploy/aws/sns",
2957
2958
  websocket: "../.deploy/aws/websocket"
2958
2959
  },
2959
2960
  ...entrypoint
package/dist/index.mjs CHANGED
@@ -2800,6 +2800,7 @@ var transformTriggerTemplate = {
2800
2800
  http: "../.deploy/aws/http",
2801
2801
  scheduler: "../.deploy/aws/scheduler",
2802
2802
  sqs: "../.deploy/aws/sqs",
2803
+ sns: "../.deploy/aws/sns",
2803
2804
  websocket: "../.deploy/aws/websocket"
2804
2805
  },
2805
2806
  ...entrypoint
@@ -98,6 +98,25 @@ module "sqs_trigger_for_<%= namespace %>_<%= module %>" {
98
98
  }
99
99
  <%_ } _%>
100
100
 
101
+ <%_
102
+ // ── Event (SNS) triggers ─────────────────────────────────────────────────────
103
+ const snsEntries = Object.entries(entries).filter(([, e]) => e.trigger.type.toLowerCase() === "event" && e.trigger.options.sourceType?.toLowerCase() === "sns");
104
+ _%>
105
+ <%_ if (snsEntries.length > 0) { _%>
106
+ module "sns_trigger_for_<%= namespace %>_<%= module %>" {
107
+ source = "<%= tfModules.sns %>"
108
+ lambda_name = "<%= namespace %>_<%= module %>"
109
+ lambda_arn = data.aws_lambda_function.this.arn
110
+ event_sources = {
111
+ <%_ for (const [key, entry] of snsEntries) { _%>
112
+ "<%= key %>" = {
113
+ topic_name = "<%= entry.trigger.options.source %>"
114
+ }
115
+ <%_ } _%>
116
+ }
117
+ }
118
+ <%_ } _%>
119
+
101
120
  <%_
102
121
  // ── WebSocket triggers ───────────────────────────────────────────────────────
103
122
  const wsEntries = Object.entries(entries).filter(([, e]) => e.trigger.type.toLowerCase() === "websocket");
@@ -12,6 +12,8 @@ import <%=svc.varName%> from "<%-svc.path%>";
12
12
 
13
13
  // __dirname is injected by the esbuild banner and resolves to the workingDir/env folder
14
14
  process.env.DEV_CLOUD_LOCATION_PATH ??= path.join(__dirname, '.local-location');
15
+ process.env.DEV_CLOUD_STORAGE_BUCKET ??= path.join(__dirname, '.local-storage');
16
+ process.env.DEV_CLOUD_EMAIL_DIR ??= path.join(__dirname, '.local-email');
15
17
 
16
18
  useCloudProvider(localCloudProvider<% if (serviceOverrides.length) { %>, { serviceFactories: { <%- serviceOverrides.map(svc => `"${svc.kind}": ${svc.varName}`).join(', ') %> } }<% } %>);
17
19
 
@@ -21,8 +23,8 @@ import <%=module%>Entries from "./<%=module%>"
21
23
 
22
24
  const router = createRouter();
23
25
 
24
- router.register(queuesPlugin, { prefix: "queues", config: { persistence: { directory: path.join(__dirname, 'queue-data') } } });
25
- router.register(schedulerPlugin, { prefix: "schedules", config: { persistence: { directory: path.join(__dirname, 'scheduler-data') } } });
26
+ router.register(queuesPlugin, { prefix: "queues", config: { persistence: { directory: path.join(__dirname, '.queue-data') } } });
27
+ router.register(schedulerPlugin, { prefix: "schedules", config: { persistence: { directory: path.join(__dirname, '.scheduler-data') } } });
26
28
  router.register(devConsolePlugin, { prefix: 'console' });
27
29
  router.register(websocketsPlugin, { prefix: "websockets" });
28
30
  router.register(invokesPlugin);
@@ -34,11 +34,20 @@ async function entries(app: RouterInstance) {
34
34
  return scheduleHandler(src["<%= entry.handler %>"], job,execution)
35
35
  }});
36
36
  <%_ } _%>
37
- <%_ if(entry.trigger.type === "event") { _%>
38
- app.queues.addQueue("<%=entry.trigger.options.source%>",
37
+ <%_ if(entry.trigger.type === "event") {
38
+ // SNS-sourced entries get their own subscriber queue - a topic can have
39
+ // multiple independent subscribers, unlike a plain SQS-sourced queue
40
+ // which is addressed directly and only ever has the one consumer.
41
+ const isTopic = entry.trigger.options.sourceType === "sns";
42
+ const queueName = isTopic ? `${entry.trigger.options.source}--${module}--${name}` : entry.trigger.options.source;
43
+ _%>
44
+ app.queues.addQueue("<%=queueName%>",
39
45
  (msg) => eventBrokerHandler(src["<%= entry.handler %>"], msg),
40
46
  "<%=module%>"
41
47
  );
48
+ <%_ if(isTopic) { _%>
49
+ app.queues.subscribeTopic("<%=entry.trigger.options.source%>", "<%=queueName%>");
50
+ <%_ } _%>
42
51
  <%_ } _%>
43
52
  <%_ if(entry.trigger.type === "invoke") { _%>
44
53
  app.invokes.register("<%=module%>","<%= entry.trigger.options.name %>",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cloudnux/cli",
3
- "version": "0.19.0",
3
+ "version": "0.21.0",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",