From f607bae96ea0b4ee5f0789455b8655649449c4f2 Mon Sep 17 00:00:00 2001 From: javayhu Date: Tue, 29 Apr 2025 22:22:26 +0800 Subject: [PATCH] refactor: optimize newsletter subscribe and check status logic --- package.json | 2 +- pnpm-lock.yaml | 18 +++++----- src/newsletter/provider/resend.ts | 57 ++++++++----------------------- 3 files changed, 24 insertions(+), 53 deletions(-) diff --git a/package.json b/package.json index 38aca3c..a98b7a6 100644 --- a/package.json +++ b/package.json @@ -112,7 +112,7 @@ "remark": "^15.0.1", "remark-code-import": "^1.2.0", "remark-gfm": "^4.0.1", - "resend": "^4.3.0", + "resend": "^4.4.1", "shiki": "^2.4.2", "sonner": "^2.0.0", "stripe": "^17.6.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ea55cdd..2e4be77 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -294,8 +294,8 @@ importers: specifier: ^4.0.1 version: 4.0.1 resend: - specifier: ^4.3.0 - version: 4.3.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + specifier: ^4.4.1 + version: 4.4.1(react-dom@19.0.0(react@19.0.0))(react@19.0.0) shiki: specifier: ^2.4.2 version: 2.4.2 @@ -3197,8 +3197,8 @@ packages: '@types/node@20.17.23': resolution: {integrity: sha512-8PCGZ1ZJbEZuYNTMqywO+Sj4vSKjSjT6Ua+6RFOYlEvIvKQABPtrNkoVSLSKDb4obYcMhspVKmsw8Cm10NFRUg==} - '@types/node@20.17.24': - resolution: {integrity: sha512-d7fGCyB96w9BnWQrOsJtpyiSaBcAYYr75bnK6ZRjDbql2cGLj/3GsL5OYmLPNq76l7Gf2q4Rv9J2o6h5CrD9sA==} + '@types/node@20.17.32': + resolution: {integrity: sha512-zeMXFn8zQ+UkjK4ws0RiOC9EWByyW1CcVmLe+2rQocXRsGEDxUCwPEIVgpsGcLHS/P8JkT0oa3839BRABS0oPw==} '@types/pg@8.11.11': resolution: {integrity: sha512-kGT1qKM8wJQ5qlawUrEkXgvMSXoV213KfMGXcwfDwUIfUHXqXYXOfS1nE1LINRJVVVx5wCm70XnFlMHaIcQAfw==} @@ -5115,8 +5115,8 @@ packages: resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} engines: {node: '>=0.10.0'} - resend@4.3.0: - resolution: {integrity: sha512-4OBHeusMVSl0vcba2J3AaGzdZ1SXAAhX/Wkcwobe16AHmlW9h3li8wG62Fhvlsc61e+wlQoxcwJZP6WrBTbghQ==} + resend@4.4.1: + resolution: {integrity: sha512-FR22bzMW3VfoyZSBc8ScGo8ShrMWHmWB0G3FrispzWCnYSEEK5M7pyRvZtInKmM/09lsJETKc2q66mX+dXPSmg==} engines: {node: '>=18'} resolve-pkg-maps@1.0.0: @@ -8567,7 +8567,7 @@ snapshots: dependencies: undici-types: 6.19.8 - '@types/node@20.17.24': + '@types/node@20.17.32': dependencies: undici-types: 6.19.8 optional: true @@ -8580,7 +8580,7 @@ snapshots: '@types/pg@8.11.6': dependencies: - '@types/node': 20.17.24 + '@types/node': 20.17.32 pg-protocol: 1.9.5 pg-types: 4.0.2 optional: true @@ -10927,7 +10927,7 @@ snapshots: require-directory@2.1.1: {} - resend@4.3.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0): + resend@4.4.1(react-dom@19.0.0(react@19.0.0))(react@19.0.0): dependencies: '@react-email/render': 1.0.6(react-dom@19.0.0(react@19.0.0))(react@19.0.0) transitivePeerDependencies: diff --git a/src/newsletter/provider/resend.ts b/src/newsletter/provider/resend.ts index d5865a7..329ed6b 100644 --- a/src/newsletter/provider/resend.ts +++ b/src/newsletter/provider/resend.ts @@ -43,25 +43,14 @@ export class ResendNewsletterProvider implements NewsletterProvider { */ async subscribe({ email }: SubscribeNewsletterParams): Promise { try { - // First, list all contacts to find the one with the matching email - const listResult = await this.resend.contacts.list({ + // Check if the contact exists + const getResult = await this.resend.contacts.get({ + email, audienceId: this.audienceId, }); - if (listResult.error) { - console.error('Error listing contacts:', listResult.error); - return false; - } - // console.log('subscribe list result:', listResult); - // Check if the contact with the given email exists in the list - let contact = null; - if (listResult.data?.data && Array.isArray(listResult.data.data)) { - contact = listResult.data.data.find((c) => c.email === email); - } - - // console.log('subscribe params:', { email, contact }); - // If the contact does not exist, create a new one - if (!contact) { + // If contact doesn't exist, create a new one + if (getResult.error) { console.log('Creating new contact', email); const createResult = await this.resend.contacts.create({ email, @@ -69,7 +58,6 @@ export class ResendNewsletterProvider implements NewsletterProvider { unsubscribed: false, }); - // console.log('subscribe create result:', createResult); if (createResult.error) { console.error('Error creating contact', createResult.error); return false; @@ -78,20 +66,13 @@ export class ResendNewsletterProvider implements NewsletterProvider { return true; } - // If the contact already exists, update it - // NOTICE: we can not just create a new contact if this email already exists, - // because Resend will response 201, but user is not subscribed - // NOTICE: we can not update it with email if the contact not found, it will return 404, - // statusCode: 404, name: not_found, message: Contact not found + // If the contact exists, update it const updateResult = await this.resend.contacts.update({ email, audienceId: this.audienceId, unsubscribed: false, }); - // console.log('subscribe update result:', updateResult); - // NOTICE: we can not request too many times, because of the rate limit of Resend - // statusCode: 429, name: rate_limit_exceeded, message: Too many requests, you can only make 2 requests per second. if (updateResult.error) { console.error('Error updating contact', updateResult.error); return false; @@ -142,31 +123,21 @@ export class ResendNewsletterProvider implements NewsletterProvider { email, }: CheckSubscribeStatusParams): Promise { try { - // TODO: use get method to check if the contact exists with email, - // the new Resend API is not ready yet, so we use the old way to check - - // First, list all contacts to find the one with the matching email - const listResult = await this.resend.contacts.list({ + const result = await this.resend.contacts.get({ + email, audienceId: this.audienceId, }); - if (listResult.error) { - console.error('Error listing contacts:', listResult.error); + if (result.error) { + console.error('Error getting contact:', result.error); return false; } - // console.log('check newsletter params:', { email, listResult }); - // Check if the contact with the given email exists in the list - if (listResult.data?.data && Array.isArray(listResult.data.data)) { - return listResult.data.data.some( - (contact) => contact.email === email && contact.unsubscribed === false - ); - } - - // console.log('check newsletter status:', { email, subscribed: false }); - return false; + const status = !result.data?.unsubscribed; + console.log('Check subscribe status:', { email, status }); + return status; } catch (error) { - console.error('Error checking subscription status:', error); + console.error('Error checking subscribe status:', error); return false; } }