Skip to content

Commit c741c7e

Browse files
authored
feat(trigger): Support SQS trigger (#283)
1 parent 86d2cfb commit c741c7e

File tree

5 files changed

+153
-1
lines changed

5 files changed

+153
-1
lines changed

deploy/lib/deployTriggers.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,17 @@ 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:
93+
event.sqs.projectId || this.provider.getScwProject(),
94+
mnq_region: event.sqs.region || this.provider.getScwRegion(),
95+
},
96+
});
97+
}
8798
});
8899

89100
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: 33 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,9 +102,38 @@ 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`
106+
);
107+
}
108+
},
109+
sqs: (trigger) => {
110+
if (!trigger.name || !triggerNameRegex.test(trigger.name)) {
111+
throw new Error(
112+
`Invalid trigger "${
113+
trigger.name
114+
}": name is invalid, should match regex "${triggerNameRegex.toString()}"`
115+
);
116+
}
117+
if (!trigger.queue || !triggerSqsQueueRegex.test(trigger.queue)) {
118+
throw new Error(
119+
`Invalid trigger "${
120+
trigger.name
121+
}": queue is invalid, should match regex "${triggerSqsQueueRegex.toString()}"`
122+
);
123+
}
124+
if (
125+
trigger.projectId &&
126+
!triggerSqsProjectIdRegex.test(trigger.projectId)
127+
) {
128+
throw new Error(
129+
`Invalid trigger "${
130+
trigger.name
131+
}": projectId is invalid, should match regex "${triggerSqsProjectIdRegex.toString()}"`
103132
);
104133
}
134+
if (trigger.region && !REGION_LIST.includes(trigger.region)) {
135+
throw new Error(`Invalid trigger "${trigger.name}": region is unknown`);
136+
}
105137
},
106138
};
107139

tests/shared/validate.tests.js

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,4 +57,104 @@ 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(() =>
71+
this.validateTriggers([{ sqs: validTrigger }])
72+
).not.toThrow();
73+
});
74+
75+
it("Should validate SQS trigger without optional fields", () => {
76+
const validTrigger = {
77+
name: "my-sqs-trigger",
78+
queue: "my-queue-name",
79+
};
80+
81+
expect(() =>
82+
this.validateTriggers([{ sqs: validTrigger }])
83+
).not.toThrow();
84+
});
85+
86+
it("Should reject SQS trigger with invalid name", () => {
87+
const invalidTrigger = {
88+
name: "a", // too short
89+
queue: "my-queue-name",
90+
};
91+
92+
const errors = this.validateTriggers([{ sqs: invalidTrigger }]);
93+
expect(errors).toHaveLength(1);
94+
expect(errors[0]).toContain('Invalid trigger "a": name is invalid');
95+
});
96+
97+
it("Should reject SQS trigger with invalid queue name", () => {
98+
const invalidTrigger = {
99+
name: "my-sqs-trigger",
100+
queue: "a", // too short
101+
};
102+
103+
const errors = this.validateTriggers([{ sqs: invalidTrigger }]);
104+
expect(errors).toHaveLength(1);
105+
expect(errors[0]).toContain(
106+
'Invalid trigger "my-sqs-trigger": queue is invalid'
107+
);
108+
});
109+
110+
it("Should reject SQS trigger with invalid projectId", () => {
111+
const invalidTrigger = {
112+
name: "my-sqs-trigger",
113+
queue: "my-queue-name",
114+
projectId: "invalid-project-id",
115+
};
116+
117+
const errors = this.validateTriggers([{ sqs: invalidTrigger }]);
118+
expect(errors).toHaveLength(1);
119+
expect(errors[0]).toContain(
120+
'Invalid trigger "my-sqs-trigger": projectId is invalid'
121+
);
122+
});
123+
124+
it("Should reject SQS trigger with invalid region", () => {
125+
const invalidTrigger = {
126+
name: "my-sqs-trigger",
127+
queue: "my-queue-name",
128+
region: "invalid-region",
129+
};
130+
131+
const errors = this.validateTriggers([{ sqs: invalidTrigger }]);
132+
expect(errors).toHaveLength(1);
133+
expect(errors[0]).toContain(
134+
'Invalid trigger "my-sqs-trigger": region is unknown'
135+
);
136+
});
137+
138+
it("Should reject SQS trigger without name", () => {
139+
const invalidTrigger = {
140+
queue: "my-queue-name",
141+
};
142+
143+
const errors = this.validateTriggers([{ sqs: invalidTrigger }]);
144+
expect(errors).toHaveLength(1);
145+
expect(errors[0]).toContain(": name is invalid");
146+
});
147+
148+
it("Should reject SQS trigger without queue", () => {
149+
const invalidTrigger = {
150+
name: "my-sqs-trigger",
151+
};
152+
153+
const errors = this.validateTriggers([{ sqs: invalidTrigger }]);
154+
expect(errors).toHaveLength(1);
155+
expect(errors[0]).toContain(
156+
'Invalid trigger "my-sqs-trigger": queue is invalid'
157+
);
158+
});
159+
});
60160
});

0 commit comments

Comments
 (0)