Skip to content

feat(app/router): registerDownstreamRoutes extension hook (Fix B prerequisite for trawl#T15)#4242

Merged
PierreBrisorgueil merged 1 commit into
masterfrom
feat/app-router-downstream-extension-hook
Jun 3, 2026
Merged

feat(app/router): registerDownstreamRoutes extension hook (Fix B prerequisite for trawl#T15)#4242
PierreBrisorgueil merged 1 commit into
masterfrom
feat/app-router-downstream-extension-hook

Conversation

@PierreBrisorgueil

@PierreBrisorgueil PierreBrisorgueil commented Jun 3, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Adds registerDownstreamRoutes(options) as a named export of src/modules/app/app.router.js
  • Downstream Vue projects call it once from their own module file (before getRouter() is invoked from main.js) to inject coreModules, adminChildModules, and/or optionalModules without patching the shared devkit file
  • Route composition moved inside getRouter() so registry mutations made at module-init time are always visible at composition time
  • 6 new unit tests covering: baseline unchanged, coreModules + optionalModules injection, adminChildModules no-throw, stack-first ordering, isModuleActive gating

Context

This is the Fix B prerequisite for trawl#T15 (extract trawl_vue downstream routes to trawl.router.js, revert app.router.js to devkit byte-identity). Partially resolves infra#38 (no-ledger drift cleanup).

Trawl currently injects 7 module route imports + 2 modified route arrays directly into the shared app.router.js. This clean extension hook is the only path to reverting app.router.js to baseline without breaking trawl navigation.

Test plan

  • npm run lint — ESLint: No issues found
  • npm run test:unit — 2036 tests pass (123 test files)
  • All pre-existing app.router tests pass unchanged
  • New registerDownstreamRoutes describe block: 6/6 pass

Closes #4241. Partially resolves infra#38.

Summary by CodeRabbit

  • Refactor

    • Redesigned router initialization architecture to support dynamic route registration from modules during startup, improving system extensibility.
  • Tests

    • Added comprehensive test coverage for route registration functionality, including module activation states and route composition scenarios.

…nstream route injection

Closes #4241.

Add a `registerDownstreamRoutes(options)` named export that downstream Vue
projects can call before `getRouter()` is invoked to inject their own routes
without patching the shared devkit file.

Three extension points:
- `coreModules`       — unconditionally mounted (spread into coreRoutes)
- `adminChildModules` — added to adminChildModules before injectAdminChildren
- `optionalModules`   — added to optionalModules, gated by isModuleActive

Route composition is moved inside `getRouter()` so that registry mutations
made during module initialisation are always visible at composition time.

Unit tests added (6 cases): no-registration baseline, coreModules/optionalModules
injection, adminChildModules no-throw, ordering (stack-first), activation gating.
Copilot AI review requested due to automatic review settings June 3, 2026 13:37
@coderabbitai

coderabbitai Bot commented Jun 3, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: c05a2677-8609-40bc-ab31-5e4a359fba38

📥 Commits

Reviewing files that changed from the base of the PR and between 10c3f17 and 4bf0d3f.

📒 Files selected for processing (2)
  • src/modules/app/app.router.js
  • src/modules/app/tests/app.router.unit.tests.js

Walkthrough

Adds extensibility to the Vue router by introducing a registerDownstreamRoutes(options) function that accepts downstream route modules and defers their composition into the router until getRouter() is called, eliminating the need for downstream projects to directly modify the shared router file.

Changes

Downstream Route Registration Extension

Layer / File(s) Summary
Registration API and registries
src/modules/app/app.router.js
Introduces internal registries (_downstreamCoreModules, _downstreamAdminChildModules, _downstreamOptionalModules) and exports registerDownstreamRoutes(options) to allow downstream modules to inject routes by appending them into these mutable collections during initialization.
Router composition refactoring
src/modules/app/app.router.js
Refactors getRouter() to assemble coreRoutes, injected admin child modules, optional module list, and final routes array inside the function using populated registries instead of top-level constants, ensuring downstream registrations are visible at composition time.
Registration API tests
src/modules/app/tests/app.router.unit.tests.js
Validates that baseline routes persist when registration is not used, core/optional/admin modules can be injected and composed, stack-defined routes appear before downstream routes, isModuleActive gating filters optional downstream modules, and registerDownstreamRoutes is exported as a named function.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • pierreb-devkit/Vue#3864: Also modifies route composition in app.router.js to respect isModuleActive gating for conditionally mounted feature modules.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly describes the main change: adding a registerDownstreamRoutes extension hook to app.router.js. It is specific, concise, and directly related to the primary objective of the PR.
Description check ✅ Passed The description covers all required template sections: summary with bullet points, context, test plan with checkmarks, and linked issues. It provides clear details on changes made, their purpose, and validation results.
Linked Issues check ✅ Passed The PR implementation fully addresses all objectives from #4241: the registerDownstreamRoutes function supports coreModules, adminChildModules, and optionalModules injection; route composition is deferred in getRouter(); and all six unit tests specified in the issue are included and passing.
Out of Scope Changes check ✅ Passed All changes are directly scoped to the objectives: modifications to app.router.js add the extension hook and defer composition, and new tests validate the feature. No unrelated changes are present.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ 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 feat/app-router-downstream-extension-hook

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.

@codecov

codecov Bot commented Jun 3, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 99.57%. Comparing base (10c3f17) to head (4bf0d3f).

Additional details and impacted files
@@           Coverage Diff           @@
##           master    #4242   +/-   ##
=======================================
  Coverage   99.57%   99.57%           
=======================================
  Files          31       31           
  Lines        1172     1172           
  Branches      334      334           
=======================================
  Hits         1167     1167           
  Misses          5        5           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copilot AI 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.

Pull request overview

Adds a supported extension hook to app.router so downstream projects can inject additional routes/modules without patching the shared devkit router, enabling stack byte-identity and reducing merge drift.

Changes:

  • Introduces registerDownstreamRoutes(options) as a named export to register downstream coreModules, adminChildModules, and optionalModules.
  • Defers route composition into getRouter() so downstream registry mutations are reflected at router creation time.
  • Adds unit tests covering baseline behavior, downstream injections, ordering, and isModuleActive gating.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

File Description
src/modules/app/app.router.js Adds downstream route registries + registerDownstreamRoutes, and moves composition/injection into getRouter().
src/modules/app/tests/app.router.unit.tests.js Adds a dedicated registerDownstreamRoutes test suite verifying injection behavior and ordering/gating.

Comment on lines +77 to +93
const adminChildModules = [..._downstreamAdminChildModules];
injectAdminChildren(admin, adminChildModules, isModuleActive);

/**
* Organization-settings child modules — routes injected as children of the
* `/users/organizations/:organizationId` parent route via `injectModuleChildren`.
* Base devkit ships this empty; PR (c) and downstream projects populate it
* (e.g. a billing-settings tab rendered inside the org detail layout).
*
* Each module's router file should export routes with **relative** paths
* (e.g. `'billing'` rather than `'/users/organizations/:organizationId/billing'`)
* so they resolve under the org parent.
*/
const organizationChildModules = [
{ name: 'billing', routes: billingOrganizationRoutes },
];
injectModuleChildren(organizations, organizationChildModules, isModuleActive, ORG_PARENT_PATH);
Comment on lines +45 to +49
export function registerDownstreamRoutes(options = {}) {
if (options.coreModules) _downstreamCoreModules.push(...options.coreModules);
if (options.adminChildModules) _downstreamAdminChildModules.push(...options.adminChildModules);
if (options.optionalModules) _downstreamOptionalModules.push(...options.optionalModules);
}
Comment on lines +565 to +570
/**
* Each test resets modules so it gets a fresh registry (arrays start empty).
* registerDownstreamRoutes is imported from the same fresh module instance
* as getRouter, so mutations are visible to the composition.
*/
async function setupFreshModule(registerFn) {
@PierreBrisorgueil PierreBrisorgueil merged commit 54358f0 into master Jun 3, 2026
8 checks passed
@PierreBrisorgueil PierreBrisorgueil deleted the feat/app-router-downstream-extension-hook branch June 3, 2026 13:42
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.

feat(app/router): add registerDownstreamRoutes extension hook for downstream route injection

2 participants