Skip to content

Commit dc819af

Browse files
committed
feat(trigger): Support SQS trigger
1 parent 86d2cfb commit dc819af

File tree

5 files changed

+133
-1
lines changed

5 files changed

+133
-1
lines changed

deploy/lib/deployTriggers.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,16 @@ module.exports = {
8484
scw_nats_config: event.nats.scw_nats_config,
8585
});
8686
}
87+
if ("sqs" in event) {
88+
this.createMessageTrigger(application.id, {
89+
name: event.sqs.name,
90+
scw_sqs_config: {
91+
queue: event.sqs.queue,
92+
mnq_project_id: event.sqs.projectId || this.provider.getScwProject(),
93+
mnq_region: event.sqs.region || this.provider.getScwRegion()
94+
}
95+
});
96+
}
8797
});
8898

8999
return Promise.all(createTriggersPromises);

docs/events.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,11 @@ functions:
2424
mnq_nats_account_id: "nats account id"
2525
mnq_project_id: "project id"
2626
mnq_region: "fr-par"
27+
- sqs:
28+
name: my-sqs-trigger
29+
queue: "name"
30+
projectId: "project-id" # Optional
31+
region: "fr-par" # Optional
2732

2833
# Container
2934
custom:

provider/scalewayProvider.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@ class ScalewayProvider {
3535
return this.scwProject;
3636
}
3737

38+
getScwRegion() {
39+
return this.scwRegion;
40+
}
41+
3842
getFunctionCredentials() {
3943
return {
4044
apiUrl: this.apiFunctionUrl,

shared/validate.js

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@ const triggerNatsSubjectRegex = new RegExp(
4141
/^(\$?[a-zA-Z0-9_*>][a-zA-Z0-9_*>.]*){1,200}$/
4242
);
4343

44+
const triggerSqsQueueRegex = new RegExp(/^([a-zA-Z0-9-_.]){2,80}$/);
45+
const triggerSqsProjectIdRegex = triggerNatsProjectIdRegex;
46+
4447
const TRIGGERS_VALIDATION = {
4548
schedule: (trigger) => {
4649
if (!trigger.rate || !cronScheduleRegex.test(trigger.rate)) {
@@ -99,10 +102,32 @@ const TRIGGERS_VALIDATION = {
99102
!REGION_LIST.includes(trigger.scw_nats_config.mnq_region)
100103
) {
101104
throw new Error(
102-
`Trigger Schedule is invalid: ${trigger.name}, scw_nats_config.region is unknown}`
105+
`Trigger Schedule is invalid: ${trigger.name}, scw_nats_config.region is unknown`
103106
);
104107
}
105108
},
109+
sqs: (trigger) => {
110+
if (!trigger.name || !triggerNameRegex.test(trigger.name)) {
111+
throw new Error(
112+
`Invalid trigger "${trigger.name}": name is invalid, should match regex "${triggerNameRegex.toString()}"`
113+
);
114+
}
115+
if (!trigger.queue || !triggerSqsQueueRegex.test(trigger.queue)) {
116+
throw new Error(
117+
`Invalid trigger "${trigger.name}": queue is invalid, should match regex "${triggerSqsQueueRegex.toString()}"`
118+
);
119+
}
120+
if (trigger.projectId && !triggerSqsProjectIdRegex.test(trigger.projectId)) {
121+
throw new Error(
122+
`Invalid trigger "${trigger.name}": projectId is invalid, should match regex "${triggerSqsProjectIdRegex.toString()}"`
123+
);
124+
}
125+
if (trigger.region && !REGION_LIST.includes(trigger.region)) {
126+
throw new Error(
127+
`Invalid trigger "${trigger.name}": region is unknown`
128+
);
129+
}
130+
}
106131
};
107132

108133
module.exports = {

tests/shared/validate.tests.js

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,4 +57,92 @@ describe("Configuration validation test", () => {
5757
it("Should not validate a function when none are defined", () => {
5858
expect(this.isDefinedFunction("qux")).toEqual(false);
5959
});
60+
61+
describe("SQS trigger validation", () => {
62+
it("Should validate a valid SQS trigger", () => {
63+
const validTrigger = {
64+
name: "my-sqs-trigger",
65+
queue: "my-queue-name",
66+
projectId: "12345678-1234-1234-1234-123456789012",
67+
region: "fr-par",
68+
};
69+
70+
expect(() => this.validateTriggers([{ sqs: validTrigger }])).not.toThrow();
71+
});
72+
73+
it("Should validate SQS trigger without optional fields", () => {
74+
const validTrigger = {
75+
name: "my-sqs-trigger",
76+
queue: "my-queue-name",
77+
};
78+
79+
expect(() => this.validateTriggers([{ sqs: validTrigger }])).not.toThrow();
80+
});
81+
82+
it("Should reject SQS trigger with invalid name", () => {
83+
const invalidTrigger = {
84+
name: "a", // too short
85+
queue: "my-queue-name",
86+
};
87+
88+
const errors = this.validateTriggers([{ sqs: invalidTrigger }]);
89+
expect(errors).toHaveLength(1);
90+
expect(errors[0]).toContain('Invalid trigger "a": name is invalid');
91+
});
92+
93+
it("Should reject SQS trigger with invalid queue name", () => {
94+
const invalidTrigger = {
95+
name: "my-sqs-trigger",
96+
queue: "a", // too short
97+
};
98+
99+
const errors = this.validateTriggers([{ sqs: invalidTrigger }]);
100+
expect(errors).toHaveLength(1);
101+
expect(errors[0]).toContain('Invalid trigger "my-sqs-trigger": queue is invalid');
102+
});
103+
104+
it("Should reject SQS trigger with invalid projectId", () => {
105+
const invalidTrigger = {
106+
name: "my-sqs-trigger",
107+
queue: "my-queue-name",
108+
projectId: "invalid-project-id",
109+
};
110+
111+
const errors = this.validateTriggers([{ sqs: invalidTrigger }]);
112+
expect(errors).toHaveLength(1);
113+
expect(errors[0]).toContain('Invalid trigger "my-sqs-trigger": projectId is invalid');
114+
});
115+
116+
it("Should reject SQS trigger with invalid region", () => {
117+
const invalidTrigger = {
118+
name: "my-sqs-trigger",
119+
queue: "my-queue-name",
120+
region: "invalid-region",
121+
};
122+
123+
const errors = this.validateTriggers([{ sqs: invalidTrigger }]);
124+
expect(errors).toHaveLength(1);
125+
expect(errors[0]).toContain('Invalid trigger "my-sqs-trigger": region is unknown');
126+
});
127+
128+
it("Should reject SQS trigger without name", () => {
129+
const invalidTrigger = {
130+
queue: "my-queue-name",
131+
};
132+
133+
const errors = this.validateTriggers([{ sqs: invalidTrigger }]);
134+
expect(errors).toHaveLength(1);
135+
expect(errors[0]).toContain(': name is invalid');
136+
});
137+
138+
it("Should reject SQS trigger without queue", () => {
139+
const invalidTrigger = {
140+
name: "my-sqs-trigger",
141+
};
142+
143+
const errors = this.validateTriggers([{ sqs: invalidTrigger }]);
144+
expect(errors).toHaveLength(1);
145+
expect(errors[0]).toContain('Invalid trigger "my-sqs-trigger": queue is invalid');
146+
});
147+
});
60148
});

0 commit comments

Comments
 (0)