Skip to content

refactor(backend): inline single-use util layers (#1257) - #1343

Merged
LucasSantana-Dev merged 5 commits into
mainfrom
refactor/1257-inline-util-layers
Jun 12, 2026
Merged

LucasSantana-Dev merged 5 commits into
mainfrom
refactor/1257-inline-util-layers

Conversation

@LucasSantana-Dev

@LucasSantana-Dev LucasSantana-Dev commented Jun 12, 2026 •

Copy link
Copy Markdown
Owner

Closes #1257.

  • migrate artists.ts from wrapHandler to asyncHandler + global error middleware; delete routeUtils.wrapHandler
  • inline isDeveloperUser into requireAdmin; delete utils/developerAccess.ts
  • extract one shared stripUnknownFields helper across the three validators in middleware/validate.ts
  • asyncHandler now returns the promise it chains (return result.catch(next)) — no runtime behavior change (express ignores handler return values), makes the wrapper awaitable in tests
  • removed 19 artists unit tests that asserted wrapHandler middleware behavior now covered by integration tests; 11 handler-logic tests kept

Verification: backend type:check pass; backend suite 67 suites / 992 tests pass.


Summary by cubic

Refactors backend routing to use asyncHandler with global error handling and inlines developer access logic into requireAdmin. Removes two single-use utils and keeps API behavior unchanged while making handlers easier to test.

  • Refactors

    • Migrate artists route handlers from wrapHandler to asyncHandler; remove utils/routeUtils.ts.
    • Inline isDeveloperUser into requireAdmin; remove utils/developerAccess.ts (including requireDeveloperUser); update auth to import from middleware.
    • Make asyncHandler return its promise (awaitable in tests); no runtime behavior change.
  • Tests

    • Drop middleware-behavior unit tests in artists.test.ts now covered by integration; keep handler-logic tests.
    • Update tests to mock requireAdmin, pass next to handlers, and import isDeveloperUser from middleware.

Written for commit e67ab1a. Summary will update on new commits.

Review in cubic

Summary by CodeRabbit

  • Bug Fixes

    • Fixed async middleware to properly return promise rejection results.
  • Refactor

    • Consolidated developer access verification logic into the middleware module.
    • Refactored route handler architecture for improved consistency and maintainability.

- Inline isDeveloperUser from developerAccess.ts into requireAdmin middleware
- Delete unused developerAccess.ts and routeUtils.ts files
- Migrate artists routes from wrapHandler to asyncHandler pattern
- Migrate auth routes from wrapHandler to asyncHandler pattern
- Update middleware integration tests for new error handling pattern
- Remove 19 middleware-behavior unit tests from artists.test.ts (now in integration tests)
- Update developerAccess unit tests to test requireAdmin directly

Changes reduce utility-layer complexity and consolidate error handling in asyncHandler + errorHandler middleware chain.
@vercel

vercel Bot commented Jun 12, 2026 •

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
lucky Ready Ready Preview, Comment Jun 12, 2026 7:20pm

Request Review

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Your free trial has ended. If you'd like to continue receiving code reviews, you can add a payment method here.

@coderabbitai

coderabbitai Bot commented Jun 12, 2026 •

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

This PR consolidates single-use backend utility layers by moving isDeveloperUser from a standalone utils/developerAccess module into middleware/requireAdmin, refactoring artist routes from wrapHandler to asyncHandler inline handlers, and removing both unused utility files. All imports and test mocks are updated to reflect the new module locations.

Changes

Inline single-use backend utilities

Layer / File(s) Summary
Async error handling and developer access foundation
packages/backend/src/middleware/asyncHandler.ts, packages/backend/src/middleware/requireAdmin.ts
asyncHandler now returns the catch chain result explicitly. requireAdmin gains getDeveloperUserIds() and isDeveloperUser(userId?: string) implementations that read and validate developer IDs from environment, replacing the prior external utils/developerAccess module.
Refactor artist routes from wrapHandler to asyncHandler
packages/backend/src/routes/artists.ts
Route handlers (sugg, search, related, prefs, save, batch, delPref) are redefined as inline asyncHandler-wrapped functions returning JSON directly via service methods. wrapHandler import removed; Response type explicitly imported. Route registration and middleware chains remain identical.
Update isDeveloperUser imports across routes
packages/backend/src/routes/auth.ts
isDeveloperUser import changed from ../utils/developerAccess to ../middleware/requireAdmin.
Update developer access test location and coverage
packages/backend/tests/unit/utils/developerAccess.test.ts
Test suite imports isDeveloperUser from src/middleware/requireAdmin. Test for requireDeveloperUser (which was deleted) is removed, narrowing scope to isDeveloperUser parsing and matching.
Update admin and toggles integration test mocks
packages/backend/tests/integration/routes/admin.test.ts, packages/backend/tests/integration/routes/toggles.test.ts
Jest mocks redirected to mock isDeveloperUser from ../../../src/middleware/requireAdmin (accepting only userId 123456789) while delegating real requireAdmin behavior via jest.requireActual.
Update artist route unit tests for middleware-aware handlers
packages/backend/tests/unit/routes/artists.test.ts
Imports createMockNext helper; clears route registration mocks in beforeEach to prevent accumulation. All handler test invocations updated from (req, res) to (req, res, next) to match middleware-aware asyncHandler signatures. Response expectations adjusted for new inline handler formatting.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • LucasSantana-Dev/Lucky#1219: Both PRs focus on correcting async error propagation by wrapping async Express route handlers with asyncHandler (and, in the main PR, ensuring the asyncHandler wrapper returns the catch result), so the Spotify route changes depend on/align with the same asyncHandler control-flow behavior.
  • LucasSantana-Dev/Lucky#980: Both PRs modify packages/backend/src/routes/artists.ts by rewriting the route handler implementations/wrapping logic (main PR switches to asyncHandler, retrieved PR rewires endpoints to use ArtistSuggestionService), making the changes directly overlapping in the same routes file.
  • LucasSantana-Dev/Lucky#1334: Both PRs modify packages/backend/src/routes/artists.ts by changing how artist endpoints are wired/handled—main PR swaps wrapHandler/routeUtils for asyncHandler, while the retrieved PR adds Zod-based validateQuery/validateBody/validateParams middleware to the same artist search and preference routes.

Suggested labels

backend, size/m

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

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.
Out of Scope Changes check ❓ Inconclusive Changes are within scope of #1257 except the validate.ts stripUnknownFields extraction mentioned in the PR description is not reflected in the provided summaries, creating an inconsistency. Clarify whether the stripUnknownFields deduplication from validate.ts was completed as part of the acceptance criteria, or if it remains as follow-up work.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The PR title clearly summarizes the main refactoring objective: inlining single-use utility layers, which aligns with the primary changes across multiple files.
Linked Issues check ✅ Passed The PR addresses all three acceptance criteria from #1257: wrapHandler removed and artists.ts migrated to asyncHandler, developerAccess inlined into requireAdmin with file deleted, and asyncHandler return modified for testability.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ 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 refactor/1257-inline-util-layers

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.

@LucasSantana-Dev

Copy link
Copy Markdown
Owner Author

@cubic-dev-ai review

@LucasSantana-Dev
LucasSantana-Dev enabled auto-merge (squash) June 12, 2026 18:40
@cubic-dev-ai

cubic-dev-ai Bot commented Jun 12, 2026

Copy link
Copy Markdown

@cubic-dev-ai review

@LucasSantana-Dev I have started the AI code review. It will take a few minutes to complete.

@github-actions

Copy link
Copy Markdown

Failed to generate code suggestions for PR

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/backend/src/routes/artists.ts`:
- Around line 28-32: The route handler related currently defaults a missing
artistId to '' and calls svc.handleGetRelatedArtists(''), which can cause
unexpected behavior; update the route to validate artistId explicitly by either
adding validateParams middleware with a schema like
artistsSchemas.relatedArtistsParams (z.string().min(1)) at route registration or
by checking inside related (throw new AppError('Missing artistId', 400) if
r.params.artistId is falsy/not a non-empty string) before calling
svc.handleGetRelatedArtists; reference the related handler, AuthenticatedRequest
params, svc.handleGetRelatedArtists, validateParams,
artistsSchemas.relatedArtistsParams, and AppError when making the change.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 14a8af5d-dc37-4b23-ba97-bd7733b82fc2

📥 Commits

Reviewing files that changed from the base of the PR and between eb9b2ea and 871db20.

📒 Files selected for processing (10)
  • packages/backend/src/middleware/asyncHandler.ts
  • packages/backend/src/middleware/requireAdmin.ts
  • packages/backend/src/routes/artists.ts
  • packages/backend/src/routes/auth.ts
  • packages/backend/src/utils/developerAccess.ts
  • packages/backend/src/utils/routeUtils.ts
  • packages/backend/tests/integration/routes/admin.test.ts
  • packages/backend/tests/integration/routes/toggles.test.ts
  • packages/backend/tests/unit/routes/artists.test.ts
  • packages/backend/tests/unit/utils/developerAccess.test.ts
💤 Files with no reviewable changes (2)
  • packages/backend/src/utils/developerAccess.ts
  • packages/backend/src/utils/routeUtils.ts
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
  • GitHub Check: Checks
  • GitHub Check: cubic · AI code reviewer
  • GitHub Check: quality / SAST (CodeQL) (javascript-typescript)
  • GitHub Check: Build — backend
  • GitHub Check: Build — frontend
  • GitHub Check: Build — bot
🔇 Additional comments (17)
packages/backend/src/routes/artists.ts (8)

1-10: LGTM!


20-22: LGTM!


24-26: LGTM!


34-41: LGTM!


43-47: LGTM!


49-53: LGTM!


55-62: LGTM!


64-103: LGTM!

packages/backend/tests/unit/routes/artists.test.ts (3)

20-20: LGTM!


107-111: LGTM!


147-148: LGTM!

Also applies to: 178-179, 250-251, 285-286, 313-314, 343-344, 375-376, 414-415, 461-462, 490-491, 520-521

packages/backend/tests/integration/routes/toggles.test.ts (1)

19-22: Same ineffective mock pattern as packages/backend/tests/integration/routes/admin.test.ts Lines 26-29.

packages/backend/src/middleware/asyncHandler.ts (1)

14-14: LGTM!

packages/backend/src/middleware/requireAdmin.ts (1)

4-20: LGTM!

packages/backend/src/routes/auth.ts (1)

12-12: LGTM!

packages/backend/tests/unit/utils/developerAccess.test.ts (1)

2-27: LGTM!

packages/backend/tests/integration/routes/admin.test.ts (1)

26-29: isDeveloperUser mock likely doesn’t affect the real requireAdmin path

In packages/backend/tests/integration/routes/admin.test.ts (lines 26–29), the mock overrides the exported isDeveloperUser, but sets requireAdmin to jest.requireActual(...).requireAdmin, which runs the real requireAdmin implementation from packages/backend/src/middleware/requireAdmin.ts.

If requireAdmin uses a module-local isDeveloperUser binding (i.e., closes over it), the export override won’t be consulted, so the test may depend on the real predicate (potentially process.env.DEVELOPER_USER_IDS) instead of the stubbed userId.

Adjust the mock to override requireAdmin itself (or refactor requireAdmin to call the exported isDeveloperUser) so the test actually exercises the intended authorization logic.

Comment thread packages/backend/src/routes/artists.ts
cubic-dev-ai[bot]
cubic-dev-ai Bot previously approved these changes Jun 12, 2026

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

No issues found across 10 files

Auto-approved: Refactors single-use utilities into inline code or middleware. No API behavior changes, all tests pass, and logic is purely structural.

Re-trigger cubic

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Your free trial has ended. If you'd like to continue receiving code reviews, you can add a payment method here.

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Your free trial has ended. If you'd like to continue receiving code reviews, you can add a payment method here.

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Your free trial has ended. If you'd like to continue receiving code reviews, you can add a payment method here.

@LucasSantana-Dev

Copy link
Copy Markdown
Owner Author

Re cubic's artists.ts note: the typeof r.params.artistId === 'string' ? ... : '' guard is carried over verbatim from the pre-refactor wrapHandler version — this PR's contract is no behavior change. Tightening param validation is tracked separately (#1189 added it for delete-preference; the GET route can follow the same pattern if wanted).

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

0 issues found across 1 file (changes from recent commits).

Requires human review: Removes 19 artists unit tests and restructures error handling across routes. Even though the refactor appears logically safe, deleting tests and changing middleware patterns in a 656-line change carries moderate risk that warrants human review.

Re-trigger cubic

@sonarqubecloud

Copy link
Copy Markdown

@LucasSantana-Dev
LucasSantana-Dev merged commit 476f385 into main Jun 12, 2026
41 checks passed
@LucasSantana-Dev
LucasSantana-Dev deleted the refactor/1257-inline-util-layers branch June 12, 2026 19:24

This branch was successfully deployed

1 active deployment
Preview — 94c29380 Deployed Jun 12, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

refactor(backend): inline single-use util layers (wrapHandler, developerAccess, validate dedup)

1 participant