Skip to content

Menu builder

@investec/plugins-menu-builder is the menu aggregation layer for Investec Online. It decides which menu endpoints to call from auth context, merges the responses into one IMenuConfig, and maps menu IDs to region-specific URLs.

Package

sh
npm install --save @investec/plugins-menu-builder

What it owns

  • auth-driven menu endpoint selection
  • merge logic for menu trees and menu items without children
  • region-aware URL configuration through menuItemMap
  • incremental menu updates through menuBuilder.updateAppState
  • per-call success/failure tracking in callResultMap

Public contract

The package exports:

  • menuBuilder
  • setupMenu()
  • menu types such as IMenuConfig, IMenuItem
  • config exports such as menuItemMap

Integration pattern

ts
import {
  menuBuilder,
  setupMenu,
} from '@investec/plugins-menu-builder';

menuBuilder.activeEnvironment = 'staging';
menuBuilder.authResponse.next(authResponse);

menuBuilder.updateAppState.subscribe((menuConfig) => {
  // Persist or pass the menu config onward.
});

await setupMenu();

Result shape

The aggregated menu config includes:

ts
interface IMenuConfig {
  mainMenu: IMenuItem[];
  mainMenuWithoutChildren: IMenuItem[];
  callResultMap: { url: string; result: boolean; region: string }[];
  hasError?: boolean;
  currentMenuRegion?: string;
}

Runtime behaviour

setupMenu():

  1. derives the active menu region from auth context
  2. chooses menu endpoints from MenuUrlMap() and AdditionalClientProfileFlagsMenuUrlMap()
  3. fetches and merges menu payloads
  4. fills missing URLs through menuItemMap
  5. updates menuBuilder.updateAppState as data arrives

How consumers extend it

Consumers normally extend menu behaviour after the plugin emits its canonical menu model.

Typical patterns are:

  • subscribe to menuBuilder.updateAppState and persist the result in app state;
  • choose when to call setupMenu() based on auth lifecycle;
  • update the current region in app state before dependent consumers render;
  • decorate the built menu for one shell surface without changing the shared aggregation rules.

Change the package when a new menu endpoint, new auth-driven call rule, or new shared URL mapping is needed.

Extension example: decorate the canonical menu in app state

ts
import {
  menuBuilder,
  setupMenu,
  type IMenuConfig,
} from '@investec/plugins-menu-builder';

type DecoratedMenuState = {
  menuConfig: IMenuConfig;
  hasVisibleItems: boolean;
};

let latestMenuState: DecoratedMenuState | undefined;

menuBuilder.activeEnvironment = 'staging';
menuBuilder.authResponse.next(authResponse);

menuBuilder.updateAppState.subscribe((menuConfig) => {
  latestMenuState = {
    menuConfig,
    hasVisibleItems:
      menuConfig.mainMenu.length > 0 ||
      menuConfig.mainMenuWithoutChildren.length > 0,
  };
});

await setupMenu();

Consumer notes

  • The package keeps module-level state and expects authResponse to be pushed in before setupMenu().
  • URL mapping is coupled to menu-item IDs and the current region.
  • clearState.next() resets the current config back to the default empty menu.
  • hasError is raised through callResultMap updates when one or more menu calls fail.