Appearance
Portfolio builder
@investec/plugins-portfolio-builder retrieves the portfolios allowed by the authenticated client context, stores them in a shared state object, and keeps net-worth totals up to date.
Package
Warning: This package must be installed only by the platform team into the Investec Online shell application. Never add it as a direct dependency of a consumer/feature application. Consumers use this plugin's behaviour through the Invsy SDK, or by contributing a bounded, governed change to this plugin's own source (see Plugin change governance).
sh
npm install --save @investec/plugins-portfolio-builderThe platform owns installation of released plugin versions. A consuming team normally contributes shared portfolio logic in this repository and then asks the platform team to adopt the published version.
What it owns
- environment-aware portfolio endpoint selection
- direct fetch helpers for individual portfolio types
- aggregate state in
portfolioBuilder - totals calculation across included portfolios
- optional exclusions from totals
- streamed multi-portfolio loading through
getAllPortfoliosStream(...)
Public contract
The main package-root exports include:
portfolioBuilderportfolio- portfolio types such as
IPortfolioEntity
portfolioBuilder contains:
activeEnvironmentprofileSwitchupdateAppStatecurrentPortfolioStateauthResponseclearState
Integration pattern
Set the environment and auth context first:
ts
import { portfolio, portfolioBuilder } from '@investec/plugins-portfolio-builder';
portfolioBuilder.activeEnvironment = 'staging';
portfolioBuilder.authResponse.next(authResponse);
portfolioBuilder.updateAppState.subscribe((state) => {
// Persist or forward portfolio state.
});Use direct fetch methods when you need one portfolio:
ts
await portfolio.getPrivateBankZAPortfolio('ZAR', profileId);Use the streaming method when a shell or SDK host needs the full aggregate flow:
ts
portfolio.getAllPortfoliosStream(target);target must match the exported HookTarget shape and provide source.postMessage(...).
Runtime behaviour
Direct methods such as getPrivateBankZAPortfolio(...), getPrivateBankUKPortfolio(...), getWealthAndInvestmentZAPortfolio(...), getAllNonInvestecAccounts(...), and the other portfolio-specific methods:
- fetch the relevant endpoint
- merge the response into
currentPortfolioState - update totals
- push the new state through
updateAppState
getAllPortfoliosStream(...) orchestrates those methods from auth context and posts intermediate and final results through target.source.postMessage(...) using __id: 'portfolio.stream'.
State shape
The aggregate state includes:
portfoliostotalscallResultMapcurrencycontactDataexcludes
Totals are recalculated whenever portfolios or exclusions change.
How consumers extend it
Consumers extend this package through orchestration and post-processing:
- push
authResponseand selected-profile context before calling portfolio methods; - call direct portfolio methods when only one portfolio family is needed;
- use
getAllPortfoliosStream(...)when a host needs incremental updates; - use
UpdatePortfolioExcludes(...)to change which loaded portfolios contribute to totals; - persist or transform the emitted state for product-specific rendering.
Change the package when a new portfolio family, endpoint, contact-data rule, or shared aggregation rule is needed.
Extension example: load one portfolio family and exclude it from totals
ts
import { portfolio, portfolioBuilder, type IPortfolioEntity } from '@investec/plugins-portfolio-builder';
let latestPortfolioState: IPortfolioEntity | undefined;
portfolioBuilder.activeEnvironment = 'staging';
portfolioBuilder.authResponse.next(authResponse);
portfolioBuilder.updateAppState.subscribe((state) => {
latestPortfolioState = state;
});
await portfolio.getPrivateBankZAPortfolio('ZAR', selectedProfileId);
await portfolio.UpdatePortfolioExcludes([{ flag: 'PrivateBankZA', result: true }]);
console.log(latestPortfolioState?.totals);Extend the shared plugin
| Change | Location |
|---|---|
| Add an environment-specific portfolio endpoint or switch | portfolio-builder/src/lib/environment.ts |
| Add a direct portfolio or contact-data call | portfolio in portfolio-builder/src/lib/portfolio-builder.ts |
| Include a new portfolio in the aggregate stream | getAllPortfoliosStream(...) orchestration |
| Extend aggregate state or contact data | portfolio-builder/src/lib/types/portfolio.interface.ts |
| Publish the supported addition | portfolio-builder/src/index.ts |
A new portfolio API must define its auth flag, profile and currency inputs, headers, response mapping, state key, call-result behaviour, totals inclusion, and stream completion behaviour. Add tests for eligible and ineligible auth contexts, API failure, profile switching, exclusions, and totals.
Contact the Web Platform team before changing net-worth calculations, shared currency semantics, stream message protocol, customer-data handling, or the meaning of an existing portfolio field.
Consumer notes
profileSwitchaffects how the selected profile data is interpreted by the aggregate streaming flow.- Some portfolio methods also populate
contactData. UpdatePortfolioExcludes(...)changes which portfolios contribute to totals; it does not delete the portfolio payload itself.clearState.next()resets both the current portfolio state and the cached auth response.