-
Notifications
You must be signed in to change notification settings - Fork 4.5k
Hacktober apps fix #15733
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Hacktober apps fix #15733
Conversation
BOHEUS
commented
Nov 9, 2025
- update dependencies in mailchimp, stripe and last email interaction apps
- fix logic in mailchimp integration, now it's triggered by update of People records and allows for update Mailchimp records
- fix logic in stripe integration, now properly reads data from webhook
- update READMEs to make it more understandable to non-technical users
...s/twenty-apps/hacktoberfest-2025/stripe-synchronizer/serverlessFunctions/stripe/src/index.ts
Outdated
Show resolved
Hide resolved
...ty-apps/hacktoberfest-2025/mailchimp-synchronizer/serverlessFunctions/mailchimp/src/index.ts
Show resolved
Hide resolved
...s/twenty-apps/hacktoberfest-2025/stripe-synchronizer/serverlessFunctions/stripe/src/index.ts
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Greptile Overview
Greptile Summary
This PR updates three Hacktoberfest apps with dependency updates, logic fixes, and enhanced functionality for the Twenty CRM integration ecosystem.
Key Changes:
- Updated
twenty-sdkandaxiosdependencies across all three apps - Last Email Interaction: Refactored to extract helper functions, removed unnecessary delays, and fixed event property access from
properties.receivedAttoproperties.after.receivedAt - Mailchimp Synchronizer: Added update functionality (triggered by
person.updated), introduced proper type definitions, and addedUPDATE_PERSONenvironment variable to control update behavior - Stripe Synchronizer: Extended to handle both company and person entities, extracted types to separate file, improved webhook data reading from
stripe.data.objectstructure, and added field creation for person objects - Updated READMEs across all apps for better clarity
Critical Issues Found:
- API response structure bugs in last-email-interaction and stripe-synchronizer that will cause runtime failures
- Inverted comparison logic in mailchimp-synchronizer causing updates when records are identical
- Incorrect parameter passing in recursive pagination call
- Wrong variable assignment preventing company ID propagation
Confidence Score: 1/5
- This PR contains multiple critical logical errors that will cause runtime failures and prevent the apps from functioning correctly
- The PR introduces 4 critical logic bugs that will cause runtime errors: incorrect API response path access, inverted comparison logic, wrong recursive parameter, and incorrect variable assignment. These bugs will prevent the apps from working as intended. While the overall architecture improvements and refactoring are good, the logical errors need to be fixed before merge.
- All three main serverless function files require immediate attention:
packages/twenty-apps/hacktoberfest-2025/last-email-interaction/serverlessFunctions/test/src/index.ts,packages/twenty-apps/hacktoberfest-2025/mailchimp-synchronizer/serverlessFunctions/mailchimp/src/index.ts, andpackages/twenty-apps/hacktoberfest-2025/stripe-synchronizer/serverlessFunctions/stripe/src/index.ts
Important Files Changed
File Analysis
| Filename | Score | Overview |
|---|---|---|
| packages/twenty-apps/hacktoberfest-2025/last-email-interaction/serverlessFunctions/test/src/index.ts | 2/5 | Refactored to extract helper functions and fix event property access, but contains critical API response structure bug |
| packages/twenty-apps/hacktoberfest-2025/mailchimp-synchronizer/serverlessFunctions/mailchimp/src/index.ts | 1/5 | Added update functionality and proper type definitions, but contains inverted comparison logic and incorrect cursor parameter in recursive call |
| packages/twenty-apps/hacktoberfest-2025/stripe-synchronizer/serverlessFunctions/stripe/src/index.ts | 1/5 | Added person entity handling and improved type safety, but contains incorrect status code check and wrong variable assignment |
| packages/twenty-apps/hacktoberfest-2025/stripe-synchronizer/serverlessFunctions/stripe/src/types.ts | 4/5 | New file extracting type definitions for better organization, though uses enum contrary to style guidelines |
Sequence Diagram
sequenceDiagram
participant User
participant TwentyDB as Twenty Database
participant LastEmailApp as Last Email Interaction App
participant MailchimpApp as Mailchimp Synchronizer
participant StripeApp as Stripe Synchronizer
participant Mailchimp as Mailchimp API
participant Stripe as Stripe API
Note over TwentyDB,MailchimpApp: Message Interaction Flow
User->>TwentyDB: Create/Update Message
TwentyDB->>LastEmailApp: Trigger message.created/updated event
LastEmailApp->>TwentyDB: Check if custom fields exist
alt Fields don't exist
LastEmailApp->>TwentyDB: Create lastInteraction and interactionStatus fields
end
LastEmailApp->>TwentyDB: Get message details with participants
LastEmailApp->>TwentyDB: Fetch related people IDs
LastEmailApp->>TwentyDB: Fetch related company IDs for each person
LastEmailApp->>TwentyDB: Update people records with interaction data
LastEmailApp->>TwentyDB: Update company records with interaction data
Note over TwentyDB,Mailchimp: Person to Mailchimp Sync Flow
User->>TwentyDB: Update Person Record
TwentyDB->>MailchimpApp: Trigger person.updated event
MailchimpApp->>TwentyDB: Fetch company data (if required)
MailchimpApp->>Mailchimp: Check if person exists in Mailchimp
alt Person exists in Mailchimp
MailchimpApp->>MailchimpApp: Compare records
alt Records differ and UPDATE_PERSON=true
MailchimpApp->>Mailchimp: Update person in Mailchimp
end
else Person doesn't exist
MailchimpApp->>Mailchimp: Add new person to Mailchimp
end
Note over Stripe,TwentyDB: Stripe Subscription Sync Flow
Stripe->>StripeApp: Webhook: subscription.created/updated
StripeApp->>Stripe: Get customer data
StripeApp->>TwentyDB: Check if custom fields exist
alt Fields don't exist
StripeApp->>TwentyDB: Create seats and subStatus fields
end
StripeApp->>TwentyDB: Check if company exists by business name
alt Company doesn't exist
StripeApp->>TwentyDB: Create company with subscription data
else Company exists
StripeApp->>TwentyDB: Update company with subscription data
end
StripeApp->>TwentyDB: Check if person exists by email
alt Person doesn't exist
StripeApp->>TwentyDB: Create person linked to company
else Person exists
StripeApp->>TwentyDB: Update person with subscription data
end
14 files reviewed, 6 comments
.../twenty-apps/hacktoberfest-2025/last-email-interaction/serverlessFunctions/test/src/index.ts
Show resolved
Hide resolved
...ty-apps/hacktoberfest-2025/mailchimp-synchronizer/serverlessFunctions/mailchimp/src/index.ts
Show resolved
Hide resolved
...ty-apps/hacktoberfest-2025/mailchimp-synchronizer/serverlessFunctions/mailchimp/src/index.ts
Show resolved
Hide resolved
...s/twenty-apps/hacktoberfest-2025/stripe-synchronizer/serverlessFunctions/stripe/src/types.ts
Outdated
Show resolved
Hide resolved
...s/twenty-apps/hacktoberfest-2025/stripe-synchronizer/serverlessFunctions/stripe/src/index.ts
Outdated
Show resolved
Hide resolved
...s/twenty-apps/hacktoberfest-2025/stripe-synchronizer/serverlessFunctions/stripe/src/index.ts
Outdated
Show resolved
Hide resolved
martmull
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice changes thank you, some comments but not blocking
| type stripeItem = { | ||
| quantity: number; | ||
| }; | ||
|
|
||
| type stripeItemsData = { | ||
| data: stripeItem[]; | ||
| }; | ||
|
|
||
| type stripeEventObject = { | ||
| customer: string; | ||
| items: stripeItemsData; | ||
| status: stripeStatus; | ||
| quantity: number | null; | ||
| }; | ||
|
|
||
| type stripeEventData = { | ||
| object: stripeEventObject; | ||
| }; | ||
|
|
||
| export type stripeEvent = { | ||
| data: stripeEventData; | ||
| type: string; | ||
| }; | ||
|
|
||
| export type stripeCustomer = { | ||
| businessName?: string; | ||
| name: string | null; | ||
| email: string | null; | ||
| }; | ||
|
|
||
| export type twentyObject = { | ||
| id: string; | ||
| nameSingular: string; | ||
| fields: Record<string, any>[]; | ||
| }; No newline at end of file |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you can probably export that from stripe sdk
| ## Todo | ||
| - add validation of signature key from Stripe to ensure that incoming request is valid | ||
| - add validation of signature key from Stripe to ensure that incoming request is valid | ||
| (possible once request headers are exposed to serverless functions) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
duly noted ^^
| const checkIfStripePersonExistsInTwenty = async (email: string | null) => { | ||
| const options = { | ||
| method: 'GET', | ||
| headers: { | ||
| Authorization: `Bearer ${TWENTY_API_KEY}`, | ||
| 'Content-Type': 'application/json', | ||
| }, | ||
| url: `${TWENTY_API_URL}/people?filter=emails.primaryEmail%5Beq%5D%3A%22${email}%22`, // mail is unique by default so there can be only 1 person with given mail | ||
| }; | ||
| try { | ||
| const response = await axios.request(options); | ||
| return response.status === 200 && | ||
| response.data.data.people[0].id !== undefined | ||
| ? (response.data.data.people[0].id as string) | ||
| : ''; | ||
| } catch (error) { | ||
| if (axios.isAxiosError(error)) { | ||
| throw error; | ||
| } | ||
| } | ||
| }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
would be easier to use the Stripe node sdk I guess -> https://github.com/stripe/stripe-node
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Stripe library will be used once headers are exposed to validate the webhook signature, I try to keep apps minimalistic as much as it's possible
|
Thanks @BOHEUS for your contribution! |
- update dependencies in mailchimp, stripe and last email interaction apps - fix logic in mailchimp integration, now it's triggered by update of People records and allows for update Mailchimp records - fix logic in stripe integration, now properly reads data from webhook - update READMEs to make it more understandable to non-technical users
