Skip to content

Commit c269dd7

Browse files
authored
fix(bff): handle existing contacts in brevo (#377)
1 parent c067c84 commit c269dd7

File tree

2 files changed

+77
-22
lines changed

2 files changed

+77
-22
lines changed

libs/blog-bff/newsletter/src/lib/api.ts

Lines changed: 53 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -49,30 +49,62 @@ app.post('/subscribe', async (c) => {
4949
}
5050

5151
try {
52-
const parsedNewSubscriber = emailSchema.parse(newSubscriber);
52+
const parsedEmail = emailSchema.parse(newSubscriber);
5353
const client = new NewsletterClient(BREVO_API_URL, BREVO_API_KEY);
54+
let sendTemplate = true;
5455

55-
await client.createContact({
56-
email: parsedNewSubscriber,
57-
emailBlacklisted: false,
58-
listIds,
59-
smsBlacklisted: false,
60-
});
61-
62-
const template = await client.getTemplate(templateId);
63-
64-
await client.sendEmail({
65-
sender: {
66-
id: template.sender.id,
67-
},
68-
subject: template.subject,
69-
htmlContent: template.htmlContent,
70-
to: [
71-
{
72-
email: parsedNewSubscriber,
56+
try {
57+
const existingContact = await client.getContact(parsedEmail);
58+
const mergedListIds = Array.from(
59+
new Set([...existingContact.listIds, ...listIds]),
60+
);
61+
const alreadySubscribed = listIds.some((listId) =>
62+
existingContact.listIds.includes(listId),
63+
);
64+
65+
if (!alreadySubscribed) {
66+
await client.updateContact({
67+
email: parsedEmail,
68+
emailBlacklisted: false,
69+
smsBlacklisted: false,
70+
listIds: mergedListIds,
71+
});
72+
}
73+
74+
// Contact is already on the list, we should not send a welcoming template
75+
sendTemplate = !alreadySubscribed;
76+
} catch (err) {
77+
if (
78+
typeof err === 'object' &&
79+
err &&
80+
'code' in err &&
81+
err.code === 'document_not_found'
82+
) {
83+
await client.createContact({
84+
email: parsedEmail,
85+
emailBlacklisted: false,
86+
smsBlacklisted: false,
87+
listIds,
88+
});
89+
}
90+
}
91+
92+
if (sendTemplate) {
93+
const template = await client.getTemplate(templateId);
94+
95+
await client.sendEmail({
96+
sender: {
97+
id: template.sender.id,
7398
},
74-
],
75-
});
99+
subject: template.subject,
100+
htmlContent: template.htmlContent,
101+
to: [
102+
{
103+
email: parsedEmail,
104+
},
105+
],
106+
});
107+
}
76108

77109
return c.json({ success: true }, 200);
78110
} catch (e) {

libs/blog-bff/newsletter/src/lib/newsletter-client.ts

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,22 @@ export class NewsletterClient {
2424
});
2525
}
2626

27+
getContact(email: string): Promise<{ listIds: number[] }> {
28+
return this.request<{ listIds: number[] }>(
29+
`contacts/${encodeURIComponent(email)}`,
30+
);
31+
}
32+
33+
updateContact(contact: NewContactDto): Promise<void> {
34+
return this.request<void>(`contacts/${encodeURIComponent(contact.email)}`, {
35+
method: 'PUT',
36+
body: contact,
37+
});
38+
}
39+
2740
private async request<T>(
2841
url: string,
29-
options?: { method?: 'GET' | 'POST'; body?: Record<string, any> },
42+
options?: { method?: 'GET' | 'POST' | 'PUT'; body?: Record<string, any> },
3043
): Promise<T> {
3144
const res = await fetch(`${this._baseUrl}${url}`, {
3245
method: options?.method ?? 'GET',
@@ -36,6 +49,16 @@ export class NewsletterClient {
3649
},
3750
...(options?.body && { body: JSON.stringify(options.body) }),
3851
});
52+
53+
if (!res.ok) {
54+
const errorBody = await res.json();
55+
throw new Error(errorBody);
56+
}
57+
58+
if (res.status === 204) {
59+
return {} as T;
60+
}
61+
3962
return await res.json();
4063
}
4164
}

0 commit comments

Comments
 (0)