Skip to content

refactor(plg): split plg-onboarding into named helpers and pure modules#2302

Open
Kanishkavijay39 wants to merge 6 commits intomainfrom
chore/plg-onboarding-refactor
Open

refactor(plg): split plg-onboarding into named helpers and pure modules#2302
Kanishkavijay39 wants to merge 6 commits intomainfrom
chore/plg-onboarding-refactor

Conversation

@Kanishkavijay39
Copy link
Copy Markdown
Contributor

@Kanishkavijay39 Kanishkavijay39 commented Apr 30, 2026

Summary

Refactor of src/controllers/plg/plg-onboarding.js (originally 1975 lines: a single 700-line performAsoPlgOnboarding orchestrator and a 270-line admin update switch) into a sequence of named, self-documented helpers. No behavior change — the same 284 unit tests pass after every commit.

What moved

Pure helpers → new modules under src/controllers/plg/plg-onboarding/:

  • validation.js — hostname / SSRF-safety / EDS / AEM-CS regexes
  • internal-org.jsisInternalOrg, isInternalOrgDemoSite, getReviewerIdentity
  • notifications.jsREVIEW_REASONS, DOMAIN_* constants, deriveCheckKey
  • displacement.jsPLG_OPPORTUNITY_TYPES, hasActiveSuggestions

Orchestration split (in-file, not extracted to siblings — see Notes) — performAsoPlgOnboarding shrinks from ~700 to ~360 lines and reads top-to-bottom as named phases:

  • applyDeliveryConfig — preset/auto delivery-type branching
  • enrollPlgConfigHandlers — summit-plg + auto-suggest/auto-fix loop
  • handleTerminalError — outer catch (waitlist for EntitlementWaitlistError, ERROR otherwise)
  • handleExistingOnboardedDomain + revokeDisplacedSiteAsoEnrollment — one-domain-per-org guard with displacement
  • handlePreonboardedFastPath — PRE_ONBOARDING fast track
  • persistAndNotify(onboarding, { updatedBy }, context, opts?) — collapses 10 repeats of the setUpdatedBy → save → notify pattern; supports optional swallowSaveErrors + errorLabel for the two catch-handler call sites

Admin update BYPASS branches — extracted as module-level handlers; the switch/case in update() shrinks to four lines:

  • bypassDisplaceOnboarded (DOMAIN_ALREADY_ONBOARDED_IN_ORG)
  • bypassAemSiteCheck (AEM_SITE_CHECK)
  • bypassDomainAlreadyAssigned (DOMAIN_ALREADY_ASSIGNED)

Commits

5975382c refactor(plg): extract update controller's BYPASS branches into named handlers
66d092cd refactor(plg): collapse repeated setUpdatedBy/save/notify into persistAndNotify helper
d03d21f7 refactor(plg): extract handleExistingOnboardedDomain and handlePreonboardedFastPath
53a9ac56 refactor(plg): extract applyDeliveryConfig, enrollPlgConfigHandlers, handleTerminalError
245eabdd refactor(plg): extract pure helpers from plg-onboarding into sibling modules

Test plan

  • npx mocha test/controllers/plg/plg-onboarding.test.js → 284 passing after each commit
  • npx mocha test/controllers/plg/ → 296 passing (full PLG controller suite)
  • npx eslint src/controllers/plg/plg-onboarding.js src/controllers/plg/plg-onboarding/ → clean
  • Reviewer: verify the diff is mechanical (no semantic changes). Highest-leverage spots to eyeball: Step 5c (delivery config), the displacement guard, the preonboarded fast path, and the admin BYPASS for AEM_SITE_CHECK (siteConfig mutation).
  • If extra confidence wanted: npx mocha --require test/it/postgres/harness.js --timeout 30000 'test/it/postgres/**/*.test.js'

Notes / follow-ups

  • Helpers depending on stubbed external packages (postPlgOnboardingNotification, ensureAsoEntitlement, LD updater, project resolver, revokeAsoSiteEnrollments) had to stay in the main file because esmock's 2nd-arg mocks only intercepts the entry file's direct imports — moving them to siblings broke 8+ tests. Updating ~8 esmock(...) calls to use the 3rd-arg globalDefs was tried and reverted; it caused timeouts (over-broad mocking of transitive deps). Worth a follow-up if we want to spin off entitlements.js / launch-darkly.js modules.
  • Two controller-level postPlgOnboardingNotification call sites in update() were intentionally left untouched (no updatedBy in scope; persistAndNotify doesn't fit cleanly there).
  • Total file size grew slightly (1975 → ~2060 across the family) due to JSDoc on every new helper. Cognitive complexity dropped substantially in exchange.

Kanishka added 6 commits April 30, 2026 23:57
…modules

Extract validation regex/helpers, internal-org/reviewer helpers, notification
constants + deriveCheckKey, and displacement check (hasActiveSuggestions) into
dedicated modules under src/controllers/plg/plg-onboarding/. Helpers that
depend on stubbed external packages (postPlgOnboardingNotification,
ensureAsoEntitlement, LD flag updates, project resolution) stay in main file
because esmock 2nd-arg mocks don't propagate to sibling modules.

No behavior change. 284 unit tests pass.
…handleTerminalError

Pull three well-bounded sub-procedures out of performAsoPlgOnboarding:

- applyDeliveryConfig: ~90 lines of preset/auto delivery-type branching
  (AEM_CS / AEM_EDGE / AEM_AMS / other). Mutates site + steps; returns
  rumHost (from the auto path) or null.
- enrollPlgConfigHandlers: the summit-plg + auto-suggest/auto-fix handler
  enable loop. Handler list lifted to module-level PLG_CONFIG_HANDLERS.
- handleTerminalError: the outer catch block. Persists WAITLISTED for
  EntitlementWaitlistError or ERROR for everything else, notifies, and
  either returns (waitlist) or rethrows.

No behavior change. 284 unit tests pass.
…oardedFastPath

Pull two more sub-procedures out of performAsoPlgOnboarding:

- handleExistingOnboardedDomain: ~80 lines enforcing the one-domain-per-IMS-org
  guard. Either displaces the prior onboarded domain (waitlist + revoke ASO
  enrollment + disable summit-plg) when it has no active suggestions and falls
  through, or waitlists the new request as a terminal result. The displacement
  enrollment-revoke path is further split into revokeDisplacedSiteAsoEnrollment.
- handlePreonboardedFastPath: ~115 lines of the PRE_ONBOARDING fast track
  (resolve org, reassign from internal/demo if needed, ensure entitlement,
  revoke previous enrollments, LD flags, ONBOARDED). Returns null when the
  preonboarded site can't be found, so the caller falls through to the full
  onboarding flow.

performAsoPlgOnboarding shrinks from ~700 to ~400 lines and now reads
top-to-bottom as a sequence of named steps. No behavior change. 284 unit
tests pass.
…tAndNotify helper

The pattern

  if (updatedBy) { onboarding.setUpdatedBy(updatedBy); }
  await onboarding.save();
  await postPlgOnboardingNotification(onboarding, context);

repeated 10 times across performAsoPlgOnboarding and the extracted phase
helpers, sometimes wrapped in a try/catch that logs (but does not rethrow)
save failures with a fixed label. Replace with persistAndNotify(onboarding,
{ updatedBy }, context, opts) — opts={swallowSaveErrors,errorLabel} for the
two catch-handler call sites that need to preserve the original error.

Two controller-level call sites in update() are left untouched because
updatedBy is not in scope there.

No behavior change. 284 unit tests pass.
… handlers

The PlgOnboardingController.update method had a 165-line switch/case for the
three BYPASS scenarios. Pull each branch out as a module-level async function:

- bypassDisplaceOnboarded (DOMAIN_ALREADY_ONBOARDED_IN_ORG): waitlist + offboard
  the prior domain, revoke its ASO enrollments, then re-run PLG flow.
- bypassAemSiteCheck (AEM_SITE_CHECK): validate + normalize admin-supplied
  delivery type / authorUrl, then re-run PLG flow with presets.
- bypassDomainAlreadyAssigned (DOMAIN_ALREADY_ASSIGNED): handle alternateDomain
  (retire current, onboard alt) or moveSite (transfer site to current org).

The switch in update() shrinks to four lines and each handler is self-contained
with its own JSDoc. No behavior change. 284 unit tests pass.
… normalization, IMS resolution)

The admin GET /plg/sites handler had a 110-line body mixing four concerns:
limit parsing, list-shape normalization, N+1 IMS email resolution, and DTO
composition. Extract the first three as module-level helpers, leaving the
controller method at ~50 lines focused on auth + DTO composition.

- parsePlgListLimit: returns { options } or { error } for the limit input.
- normalizePlgListResult: coerces array / single-instance / null shapes from
  the data-access BaseCollection into an array (or null on unexpected shape).
- resolveImsEmailsForPlgRecords: collects unique imsIds from updatedBy +
  reviewedBy and resolves them via imsClient in batches of 10. The standing
  TODO about a per-record endpoint moves with this helper.

The N+1 itself is preserved (existing perf TODO still applies). No behavior
change. 284 unit tests pass.
@github-actions
Copy link
Copy Markdown

This PR will trigger no release when merged.

@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 30, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

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