Skip to content

refactor: replace Apollo Client with Prisma for user data retrieval i…#8872

Open
mikeallisonJS wants to merge 2 commits intomainfrom
00-00-MA-refactor-journeys-modern-email-prisma
Open

refactor: replace Apollo Client with Prisma for user data retrieval i…#8872
mikeallisonJS wants to merge 2 commits intomainfrom
00-00-MA-refactor-journeys-modern-email-prisma

Conversation

@mikeallisonJS
Copy link
Collaborator

@mikeallisonJS mikeallisonJS commented Mar 18, 2026

…n email service

Summary by CodeRabbit

  • Bug Fixes
    • Updated email subject line for journey invitations to include "on NextSteps" for improved clarity in user communications.

@mikeallisonJS mikeallisonJS requested a review from csiyang March 18, 2026 01:48
@mikeallisonJS mikeallisonJS self-assigned this Mar 18, 2026
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 18, 2026

Walkthrough

The changes replace Apollo Client GraphQL-based user lookups with Prisma database queries throughout the email service implementation and its corresponding tests. Apollo client initialization, GraphQL query definitions, and associated mocks are removed and replaced with Prisma user.findUnique and user.findMany calls.

Changes

Cohort / File(s) Summary
Email Service & Tests
apis/api-journeys-modern/src/workers/email/service/service.ts, apis/api-journeys-modern/src/workers/email/service/service.spec.ts
Replaces Apollo Client GraphQL queries (GET_USER, GET_USER_BY_EMAIL) with Prisma database queries (findUnique, findMany) for user lookups. Service implementation removes Apollo client setup and updates all email workflows (teamRemoved, teamInvite, journeyAccessRequest, journeyEditInvite, etc.) to use Prisma-based recipient lookups with normalized user object handling. Test file updates all mocks from ApolloClient.query to Prisma mock returns, adjusts test data to match new return structures (id, email, firstName, imageUrl), and updates journeyEditInvite email subject expectation to include "on NextSteps".

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title clearly and accurately summarizes the main change: replacing Apollo Client with Prisma for user data retrieval in the email service, which is the primary objective reflected in both the file summaries and commit messages.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch 00-00-MA-refactor-journeys-modern-email-prisma
📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@nx-cloud
Copy link

nx-cloud bot commented Mar 18, 2026

View your CI Pipeline Execution ↗ for commit c39240a

Command Status Duration Result
nx affected --target=subgraph-check --base=cb11... ✅ Succeeded 1s View ↗
nx affected --target=extract-translations --bas... ✅ Succeeded <1s View ↗
nx affected --target=lint --base=cb11c74500f647... ✅ Succeeded 1s View ↗
nx affected --target=type-check --base=cb11c745... ✅ Succeeded 1s View ↗
nx run-many --target=codegen --all --parallel=3 ✅ Succeeded 2s View ↗
nx run-many --target=prisma-generate --all --pa... ✅ Succeeded 4s View ↗

☁️ Nx Cloud last updated this comment at 2026-03-18 01:55:09 UTC

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
apis/api-journeys-modern/src/workers/email/service/service.spec.ts (1)

195-200: Add regression coverage for the new lookup edge cases.

These specs only mock fully populated user rows. Please add cases for a userId lookup returning email: null and for the manager batch lookup returning fewer rows than requested, so the new recipient-resolution branches fail loudly instead of regressing silently.

Also applies to: 273-288

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apis/api-journeys-modern/src/workers/email/service/service.spec.ts` around
lines 195 - 200, Add two regression tests in service.spec.ts to exercise the
recipient-resolution error branches: 1) Create a test that stubs
mockPrismaUsers.user.findUnique (the userId lookup) to resolve to an object with
email: null (and valid id/firstName) and assert the service throws or rejects
with the expected error when resolving recipients for that userId; 2) Create a
test that stubs mockPrismaUsers.user.findMany (the manager batch lookup used by
the manager-resolution code path) to return fewer rows than the requested
manager IDs and assert the service fails loudly (throws/rejects) rather than
silently continuing. Use the same setup helpers/fixtures already present in the
file and mirror existing test structure around mockPrismaUsers.user.findUnique
and mockPrismaUsers.user.findMany so these new tests cover the two new edge
branches referenced in recipient-resolution.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apis/api-journeys-modern/src/workers/email/service/service.ts`:
- Around line 59-66: The code is coercing null emails to an empty string when
building recipient objects (see recipientUser -> user creation), which allows
invalid recipients to proceed; update the logic to 1) define a shared
EmailRecipient type/helper and use it across the places mentioned (current block
and the similar blocks at the other ranges), 2) check recipientUser.email
explicitly and if it's null/undefined return or throw before any
rendering/sending or preference lookups, and 3) replace the current spread that
sets email: recipientUser.email ?? '' with construction that only creates an
EmailRecipient when email is present (and preserve lastName handling as
optional). Locate and update the recipient construction code paths referencing
recipientUser, ensure preference/delivery functions accept the typed
EmailRecipient only, and remove the empty-string normalization.
- Around line 221-230: The code currently builds recipients via
recipientUserIds.map(id => recipientUsersByUserId.get(id)) and only throws
inside the send loop, which can cause partial delivery; modify the logic in the
block around recipients, recipientUserIds and recipientUsersByUserId to validate
the entire batch before any sends by checking for any undefined entries (e.g.,
find missingIds = recipientUserIds.filter(id => !recipientUsersByUserId.has(id))
or check recipients.some(r => r == null)) and throw a clear error (including
missing ids) if any manager is absent so the subsequent send loop over
recipients only runs when all recipients are present.

---

Nitpick comments:
In `@apis/api-journeys-modern/src/workers/email/service/service.spec.ts`:
- Around line 195-200: Add two regression tests in service.spec.ts to exercise
the recipient-resolution error branches: 1) Create a test that stubs
mockPrismaUsers.user.findUnique (the userId lookup) to resolve to an object with
email: null (and valid id/firstName) and assert the service throws or rejects
with the expected error when resolving recipients for that userId; 2) Create a
test that stubs mockPrismaUsers.user.findMany (the manager batch lookup used by
the manager-resolution code path) to return fewer rows than the requested
manager IDs and assert the service fails loudly (throws/rejects) rather than
silently continuing. Use the same setup helpers/fixtures already present in the
file and mirror existing test structure around mockPrismaUsers.user.findUnique
and mockPrismaUsers.user.findMany so these new tests cover the two new edge
branches referenced in recipient-resolution.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 0ba6bdf0-7f1f-4cfb-9512-4e10d75f4115

📥 Commits

Reviewing files that changed from the base of the PR and between cb11c74 and c39240a.

📒 Files selected for processing (2)
  • apis/api-journeys-modern/src/workers/email/service/service.spec.ts
  • apis/api-journeys-modern/src/workers/email/service/service.ts

Comment on lines +59 to +66
const user =
recipientUser == null
? null
: {
...recipientUser,
email: recipientUser.email ?? '',
lastName: recipientUser.lastName ?? undefined
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Don't coerce missing email addresses into sendable recipients.

The users schema allows email to be null for these userId-based lookups, but these branches normalize it to '' and later use that value for preference lookups and delivery. Please guard email explicitly and return/throw before rendering or sending; extracting a shared EmailRecipient type/helper would also remove the repeated object-shape copies here.

As per coding guidelines **/*.{ts,tsx}: Define a type if possible.

Also applies to: 210-218, 290-297, 349-356

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apis/api-journeys-modern/src/workers/email/service/service.ts` around lines
59 - 66, The code is coercing null emails to an empty string when building
recipient objects (see recipientUser -> user creation), which allows invalid
recipients to proceed; update the logic to 1) define a shared EmailRecipient
type/helper and use it across the places mentioned (current block and the
similar blocks at the other ranges), 2) check recipientUser.email explicitly and
if it's null/undefined return or throw before any rendering/sending or
preference lookups, and 3) replace the current spread that sets email:
recipientUser.email ?? '' with construction that only creates an EmailRecipient
when email is present (and preserve lastName handling as optional). Locate and
update the recipient construction code paths referencing recipientUser, ensure
preference/delivery functions accept the typed EmailRecipient only, and remove
the empty-string normalization.

Comment on lines +221 to +230
const recipients = recipientUserIds.map((userId) =>
recipientUsersByUserId.get(userId)
)

if (recipients.length === 0) {
throw new Error('Team Managers not found')
}

for (const recipient of recipientEmails) {
if (recipient.user == null) throw new Error('User not found')
for (const recipient of recipients) {
if (recipient == null) throw new Error('User not found')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Validate the full manager batch before the first send.

recipientUsersByUserId.get(userId) can still be undefined when one of the manager records is missing. Because that check happens inside the send loop, earlier managers may already have been emailed before the function throws, leaving the batch partially delivered.

Suggested guard
 const recipients = recipientUserIds.map((userId) =>
   recipientUsersByUserId.get(userId)
 )
 
-if (recipients.length === 0) {
+if (recipients.length === 0 || recipients.some((recipient) => recipient == null)) {
   throw new Error('Team Managers not found')
 }
 
 for (const recipient of recipients) {
-  if (recipient == null) throw new Error('User not found')
-
   // check recipient preferences
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const recipients = recipientUserIds.map((userId) =>
recipientUsersByUserId.get(userId)
)
if (recipients.length === 0) {
throw new Error('Team Managers not found')
}
for (const recipient of recipientEmails) {
if (recipient.user == null) throw new Error('User not found')
for (const recipient of recipients) {
if (recipient == null) throw new Error('User not found')
const recipients = recipientUserIds.map((userId) =>
recipientUsersByUserId.get(userId)
)
if (recipients.length === 0 || recipients.some((recipient) => recipient == null)) {
throw new Error('Team Managers not found')
}
for (const recipient of recipients) {
// check recipient preferences
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apis/api-journeys-modern/src/workers/email/service/service.ts` around lines
221 - 230, The code currently builds recipients via recipientUserIds.map(id =>
recipientUsersByUserId.get(id)) and only throws inside the send loop, which can
cause partial delivery; modify the logic in the block around recipients,
recipientUserIds and recipientUsersByUserId to validate the entire batch before
any sends by checking for any undefined entries (e.g., find missingIds =
recipientUserIds.filter(id => !recipientUsersByUserId.has(id)) or check
recipients.some(r => r == null)) and throw a clear error (including missing ids)
if any manager is absent so the subsequent send loop over recipients only runs
when all recipients are present.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant