hackathon-starter's auth and API layer carries the highest activity risk — 5 functions to address first

Five critical-band functions in config/passport.js, config/token-revocation.js, and controllers/api.js are both structurally complex and actively changing, making them live regression risks in hackathon-starter's auth and API subsystems.

Stephen Collins ·
oss javascript refactoring code-health

Antipatterns Detected

exit_heavy5complex_branching2god_function2long_function2deeply_nested1hub_function1

Key Points

What is an exit-heavy function and why does it matter in hackathon-starter?

An exit-heavy function has many return or throw statements scattered throughout its body rather than a single exit point, meaning execution can terminate in numerous places depending on conditions. In hackathon-starter, all five top hotspots carry this pattern — including revokeToken with 29 cyclomatic complexity paths and fetchAndCacheTraktImage with 15 — which means test suites must exercise a large number of distinct code trajectories just to achieve basic coverage. Each unmapped exit path is a gap where a regression can hide undetected during active development.

How do I reduce cyclomatic complexity in JavaScript?

The most direct technique is the extract-method refactoring: pull each major conditional branch into a descriptively named function, so the parent function reads as a sequence of intent-revealing calls rather than a tree of nested logic. For token-handling code like revokeToken, grouping per-provider logic into separate functions is a natural split that can bring a CC of 29 down to single-digit complexity per unit.

Is hackathon-starter actively maintained?

The data suggests yes — all five top hotspots are classified in the 'fire' quadrant, meaning they combine high structural complexity with high recent commit activity. That level of activity concentrated in the auth and API layer indicates the project is being actively developed, which is precisely what makes the structural complexity in those functions a live concern rather than dormant debt.

How do I reproduce this analysis?

Run the Hotspots CLI against the sahat/hackathon-starter repository at commit abd6b2f to reproduce these exact scores and quadrant classifications.

What does activity-weighted risk mean?

Complexity × recent commit frequency — functions that are hard to understand AND actively changing are the highest priority for refactoring.

Every one of hackathon-starter’s top five hotspots is in the ‘fire’ quadrant — structurally complex code that is actively changing, not just cleanup waiting on the backlog. The anonymous strategy handler in config/passport.js leads with an activity risk of 15.34, meaning high cyclomatic complexity and deep nesting are combining with live commit churn into a real regression surface today. Across 398 total functions, 60 are rated critical-band — that’s 15% of the codebase demanding immediate attention, concentrated almost entirely in authentication configuration and third-party API integration.

The table below ranks functions by activity-weighted risk — a score that multiplies structural complexity by recent commit frequency. A function that is both hard to understand (high cyclomatic complexity) and actively changing is a higher priority than one that is complex but untouched. CC = cyclomatic complexity (independent execution paths); ND = max nesting depth; FO = fan-out (distinct callees).

Top 5 Hotspots

FunctionFileRiskCCNDFO
<anonymous>config/passport.js15.311611
revokeTokenconfig/token-revocation.js14.529312
fetchAndCacheTraktImagecontrollers/api.js13.815314
<anonymous>controllers/api.js13.817413
handleAuthLoginconfig/passport.js13.72237

Hotspot Analysis

<anonymous> — config/passport.js

This anonymous function lives inside hackathon-starter’s Passport.js configuration, almost certainly implementing an OAuth or local authentication strategy callback — the kind of code that validates credentials, looks up or creates users, and decides whether to grant access. Its cyclomatic complexity of 11, max nesting depth of 6, and fan-out of 11 collectively describe a function that branches heavily through authentication edge cases, reaches six levels deep into nested conditionals, and touches eleven distinct external functions — a wide blast radius for any change. In the ‘fire’ quadrant with the highest activity risk in the top five, this is not dormant debt: it is structurally fragile code being actively modified right now, which makes every commit a regression risk.

Recommendation: Add characterization tests that cover each of the 11 independent paths before making any further changes, then extract the deeply nested (ND 6) credential-handling branches into named helper functions to bring nesting depth below 4.

revokeToken — config/token-revocation.js

The name and file path make the purpose clear: this function manages OAuth token revocation, likely iterating over multiple provider strategies and handling varied API responses. A cyclomatic complexity of 29 is firmly in high territory — that is 29 independent execution paths, each a required test case and a potential failure mode — and a fan-out of 12 means it calls a dozen distinct functions, giving it broad coupling across the token lifecycle. The ‘god_function’ and ‘long_function’ patterns confirm it has accumulated responsibilities that belong in separate, focused units; with high recent commit velocity, this accumulation is being actively stress-tested by ongoing commits.

Recommendation: Apply extract-method refactoring to isolate per-provider revocation logic into individual named functions, targeting a cyclomatic complexity below 10 per unit; the 12 callees (FO 12) are a map of the seams where this function can be cleanly split.

fetchAndCacheTraktImage — controllers/api.js

From its name and location in the API controller, this function almost certainly fetches an image from the Trakt.tv API and stores it in some local or in-memory cache — a task that naturally involves network calls, error handling, cache-miss logic, and response transformation. A fan-out of 14 is the standout metric here: calling 14 distinct functions means a change to any one of those dependencies could require a corresponding change here, and vice versa — broad coupling in a function that is already in the ‘fire’ quadrant with sustained recent commit activity. Its cyclomatic complexity of 15 and ‘exit_heavy’ pattern mean there are many early-return paths that are costly to test comprehensively.

Recommendation: Decompose the function along its natural seams — network fetch, error handling, and cache write — into three focused helpers, reducing both fan-out and the number of exit paths that need test coverage.

<anonymous> — controllers/api.js

This anonymous function in the API controller likely handles a specific API route or event — the kind of code that receives a request, applies conditional logic to decide what to do, and dispatches to various services. With a cyclomatic complexity of 17, it carries 17 independent execution paths, each one a distinct test case required for full coverage and a potential point of regression. A nesting depth of 4 sits at the refactoring threshold, and a fan-out of 13 means 13 distinct callees sit within the blast radius of any change. Tied with fetchAndCacheTraktImage at risk score 13.8, this function is equally active and equally fragile.

Recommendation: Identify the primary branching condition at the function’s top level and extract each major case into a named handler; the high fan-out (FO 13) provides natural extraction points and guides where existing seams already lie.

handleAuthLogin — config/passport.js

handleAuthLogin sits in the Passport configuration alongside the anonymous strategy callback and likely manages the login decision tree — validating credentials, looking up users, surfacing error states, or creating new records. Its cyclomatic complexity of 22 is substantial: twenty-two independent execution paths through the authentication entry point means a high test burden and numerous hidden failure modes that are difficult to reason about during review. While its nesting depth is more contained (ND 3), the complex_branching pattern confirms this is not incidental complexity but a structural priority. Fan-out of 7 is the most targeted in the top five, which gives it cleaner extraction boundaries than its neighbours.

Recommendation: Extract the main authentication decision branches — credential validation, user lookup, and error handling — into three separate named functions, targeting a per-unit cyclomatic complexity below 8.

Patterns Found

Antipatterns detected across the top functions in this snapshot:

PatternOccurrences
exit_heavy5
complex_branching2
god_function2
long_function2
deeply_nested1
hub_function1

These labels belong to two tiers — Tier 1 (structural): complex_branching, deeply_nested, exit_heavy, long_function, god_function. Tier 2 (relational/temporal): hub_function, cyclic_hub, middle_man, neighbor_risk, stale_complex, churn_magnet, shotgun_target, volatile_god.

Key Takeaways

  • revokeToken in config/token-revocation.js has a cyclomatic complexity of 29 and calls 12 distinct functions — write a characterization test suite covering all 29 paths before the next commit touches it.
  • The anonymous Passport strategy callback in config/passport.js reaches a nesting depth of 6, well past the ND 4 refactoring threshold; flattening it to named sub-functions will make the authentication flow reviewable in code review.
  • fetchAndCacheTraktImage in controllers/api.js has the highest fan-out in the top five (FO 14) — map its 14 callees explicitly before refactoring to avoid unintended ripple effects across the API controller.
  • The anonymous handler in controllers/api.js has CC 17 with a fan-out of 13 — extract each major branching case into a named handler to bring both metrics below 10.
  • handleAuthLogin in config/passport.js has CC 22 concentrated in the authentication entry point — splitting credential validation, user lookup, and error handling into named functions will make the login flow auditable at a glance.

Reproduce This Analysis

git clone https://github.com/sahat/hackathon-starter
cd hackathon-starter
git checkout abd6b2f0336d6af9d11a75fa95cd2f320a408120
hotspots analyze . --mode snapshot --explain-patterns --force

To run the same analysis on your own codebase, run hotspots analyze . --mode snapshot in any local git repo — no configuration required.

Hotspots highlights structural and activity risk — not “bad code.” Findings are a prioritization aid, not a bug predictor. Editorial policy →

Run this on your own codebase

Hotspots runs locally in under a minute — no account, no data leaves your machine.

macOS
$ brew install Stephen-Collins-tech/tap/hotspots
Linux / cargo
$ cargo install hotspots-cli
Run in any repo
$ hotspots analyze .
★ Star on GitHub

Related Analyses