Feat/update and delete meta templates#2163
Feat/update and delete meta templates#2163DavidsonGomes merged 3 commits intoEvolutionAPI:developfrom
Conversation
There was a problem hiding this comment.
Hey there - I've reviewed your changes - here's some feedback:
- Consolidate the instance lookup and token/businessId assignment in TemplateService into a shared private helper to reduce duplication and improve maintainability.
- Consider using PATCH instead of POST for the template edit endpoint to better align with RESTful update semantics.
- Replace console.error in the router error handlers with the project's logger to ensure consistent logging practices and severity levels.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- Consolidate the instance lookup and token/businessId assignment in TemplateService into a shared private helper to reduce duplication and improve maintainability.
- Consider using PATCH instead of POST for the template edit endpoint to better align with RESTful update semantics.
- Replace console.error in the router error handlers with the project's logger to ensure consistent logging practices and severity levels.
## Individual Comments
### Comment 1
<location> `src/api/services/template.service.ts:107` </location>
<code_context>
+ if (typeof data.category === 'string') payload.category = data.category;
+ if (typeof data.allowCategoryChange === 'boolean') payload.allow_category_change = data.allowCategoryChange;
+ if (typeof data.ttl === 'number') payload.time_to_live = data.ttl;
+ if (data.components) payload.components = data.components;
+
+ const response = await this.requestEditTemplate(data.templateId, payload);
</code_context>
<issue_to_address>
**suggestion:** Check for empty array or object in components assignment.
The current logic excludes empty arrays or objects from assignment, which may be valid. Use a check like data.components !== undefined to allow empty values if appropriate.
```suggestion
if (data.components !== undefined) payload.components = data.components;
```
</issue_to_address>
### Comment 2
<location> `src/api/services/template.service.ts:145-152` </location>
<code_context>
+
+ try {
+ // Best-effort local cleanup of stored template metadata
+ await this.prismaRepository.template.deleteMany({
+ where: {
+ OR: [
+ { name: data.name, instanceId: getInstance.id },
+ data.hsmId ? { templateId: data.hsmId, instanceId: getInstance.id } : undefined,
+ ].filter(Boolean) as any,
+ },
+ });
</code_context>
<issue_to_address>
**suggestion:** Avoid using 'as any' in Prisma query filter.
Explicitly define the filter type or refactor the query to maintain type safety and prevent hidden type errors.
```suggestion
const orFilter: Array<{ name?: string; templateId?: string; instanceId: string }> = [
{ name: data.name, instanceId: getInstance.id },
];
if (data.hsmId) {
orFilter.push({ templateId: data.hsmId, instanceId: getInstance.id });
}
await this.prismaRepository.template.deleteMany({
where: {
OR: orFilter,
},
});
```
</issue_to_address>
### Comment 3
<location> `src/api/services/template.service.ts:154-156` </location>
<code_context>
+ },
+ });
+ } catch (err) {
+ this.logger.warn(
+ `Failed to cleanup local template records after delete: ${(err as Error)?.message || String(err)}`,
+ );
</code_context>
<issue_to_address>
**suggestion:** Consider including error stack in log for better diagnostics.
Including the stack trace will provide more context for debugging cleanup failures.
```suggestion
this.logger.warn(
`Failed to cleanup local template records after delete: ${(err as Error)?.message || String(err)}\nStack: ${(err as Error)?.stack || 'No stack trace available.'}`,
);
```
</issue_to_address>
### Comment 4
<location> `src/validate/templateEdit.schema.ts:31` </location>
<code_context>
+ category: { type: 'string', enum: ['AUTHENTICATION', 'MARKETING', 'UTILITY'] },
+ allowCategoryChange: { type: 'boolean' },
+ ttl: { type: 'number' },
+ components: { type: 'array' },
+ },
+ required: ['templateId'],
</code_context>
<issue_to_address>
**suggestion:** Specify item type for components array in schema.
Defining items: { type: 'object' } for the components array will ensure proper validation and prevent invalid data.
```suggestion
components: {
type: 'array',
items: { type: 'object' }
},
```
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
| if (typeof data.category === 'string') payload.category = data.category; | ||
| if (typeof data.allowCategoryChange === 'boolean') payload.allow_category_change = data.allowCategoryChange; | ||
| if (typeof data.ttl === 'number') payload.time_to_live = data.ttl; | ||
| if (data.components) payload.components = data.components; |
There was a problem hiding this comment.
suggestion: Check for empty array or object in components assignment.
The current logic excludes empty arrays or objects from assignment, which may be valid. Use a check like data.components !== undefined to allow empty values if appropriate.
| if (data.components) payload.components = data.components; | |
| if (data.components !== undefined) payload.components = data.components; |
| await this.prismaRepository.template.deleteMany({ | ||
| where: { | ||
| OR: [ | ||
| { name: data.name, instanceId: getInstance.id }, | ||
| data.hsmId ? { templateId: data.hsmId, instanceId: getInstance.id } : undefined, | ||
| ].filter(Boolean) as any, | ||
| }, | ||
| }); |
There was a problem hiding this comment.
suggestion: Avoid using 'as any' in Prisma query filter.
Explicitly define the filter type or refactor the query to maintain type safety and prevent hidden type errors.
| await this.prismaRepository.template.deleteMany({ | |
| where: { | |
| OR: [ | |
| { name: data.name, instanceId: getInstance.id }, | |
| data.hsmId ? { templateId: data.hsmId, instanceId: getInstance.id } : undefined, | |
| ].filter(Boolean) as any, | |
| }, | |
| }); | |
| const orFilter: Array<{ name?: string; templateId?: string; instanceId: string }> = [ | |
| { name: data.name, instanceId: getInstance.id }, | |
| ]; | |
| if (data.hsmId) { | |
| orFilter.push({ templateId: data.hsmId, instanceId: getInstance.id }); | |
| } | |
| await this.prismaRepository.template.deleteMany({ | |
| where: { | |
| OR: orFilter, | |
| }, | |
| }); |
| category: { type: 'string', enum: ['AUTHENTICATION', 'MARKETING', 'UTILITY'] }, | ||
| allowCategoryChange: { type: 'boolean' }, | ||
| ttl: { type: 'number' }, | ||
| components: { type: 'array' }, |
There was a problem hiding this comment.
suggestion: Specify item type for components array in schema.
Defining items: { type: 'object' } for the components array will ensure proper validation and prevent invalid data.
| components: { type: 'array' }, | |
| components: { | |
| type: 'array', | |
| items: { type: 'object' } | |
| }, |
| } else { | ||
| const { host, password, port, protocol: proto, username } = proxy | ||
| protocol = (proto || 'http').replace(':', '') | ||
| const { host, password, port, protocol: proto, username } = proxy; |
Check failure
Code scanning / CodeQL
Insecure randomness High
| } else { | ||
| const { host, password, port, protocol: proto, username } = proxy | ||
| protocol = (proto || 'http').replace(':', '') | ||
| const { host, password, port, protocol: proto, username } = proxy; |
Check failure
Code scanning / CodeQL
Insecure randomness High
| } else { | ||
| const { host, password, port, protocol: proto, username } = proxy | ||
| protocol = (proto || 'http').replace(':', '') | ||
| const { host, password, port, protocol: proto, username } = proxy; |
Check failure
Code scanning / CodeQL
Insecure randomness High
| } else { | ||
| const { host, password, port, protocol: proto, username } = proxy | ||
| protocol = (proto || 'http').replace(':', '') | ||
| const { host, password, port, protocol: proto, username } = proxy; |
Check failure
Code scanning / CodeQL
Insecure randomness High
Check failure
Code scanning / CodeQL
Insecure randomness High

📋 Description
Adds Template management endpoints for WhatsApp Business templates.
🔗 Related Issue
Closes #(issue_number)
🧪 Type of Change
🧪 Testing
Manual checks:
/template/createwith validTemplateDtocreates template and stores metadata/template/editupdates template fields via Meta API/template/deletedeletes template by name or hsm_id and performs best-effort local cleanup/template/findretrieves templates for the instance✅ Checklist
📝 Additional Notes
WAMonitoringServicecreateMetaErrorResponseSummary by Sourcery
Add update and delete operations for WhatsApp Business message templates
New Features:
Enhancements:
Chores: