Appearance
Profiles builder
@investec/plugins-profiles-builder retrieves customer profiles and publishes them through reactive state for downstream consumers such as portfolio loading and profile selectors.
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-profiles-builderThe platform owns installation of released plugin versions. A consuming team normally contributes shared profile logic in this repository and then asks the platform team to adopt the published version.
What it owns
- fetching ZA private-bank, intermediary, and business-banking profiles
- normalising those records to include
nameandid - legacy typed collections through
updateAppState - grouped client-type profile state through
profilesList
Public contract
The main package-root exports include:
profilesBuildergetProfiles()- direct fetch helpers
getZaProfiles(),getIfaProfiles(), andgetBusinessBankingProfiles() - profile and auth-response types
profilesBuilder contains:
activeEnvironmentupdateAppStateauthResponseclearStateprofilesList
Integration pattern
ts
import { getProfiles, profilesBuilder } from '@investec/plugins-profiles-builder';
profilesBuilder.authResponse.next(authResponse);
profilesBuilder.updateAppState.subscribe((profiles) => {
// Legacy typed profile buckets.
});
profilesBuilder.profilesList.subscribe((profileList) => {
// Client-type grouped profile data.
});
getProfiles();Returned state
The plugin exposes two views of the data.
updateAppState
Legacy grouped buckets:
ts
{
PrivateBankZA: IZaProfile[];
IntermediaryBanking: IIfaProfile[];
BusinessBankingZa: IBusinessBankingProfile[];
}profilesList
Client-type grouped data for newer selectors:
ts
{
data: [
{
clientType: 'private-client',
profilesList: [{ PrivateBankZA: [...] }],
selectedProfile: [{ PrivateBankZA: selectedProfile }]
}
]
}Runtime behaviour
getProfiles() checks auth flags and calls:
/edge/base/za/pb/profiles/edge/cxt-ifi/api/v3/intermediary/edge/base/za/tbba/api/v1/users/profilesby default (configurable below)
depending on which profile families the authenticated user has available.
Business Banking profiles routing
profilesBuilder.activeEnvironment selects the businessBanking.useNewProfilesEndpoint flag in profiles-builder/src/lib/environment.ts. Supported environments are production, beta, staging, and test; the default is staging.
The flag defaults to false in every environment:
| Flag | Business Banking profiles route |
|---|---|
false | /edge/base/za/tbba/api/v1/users/profiles |
true | /edge/base/za/tbb/api/v1/users/profiles |
This is a packaged configuration flag, not an OS environment variable or a toggles-builder value. Changing it requires publishing the plugin and updating the platform dependency to the released version.
How consumers extend it
Consumers normally extend this package by owning profile selection and app-state projection after the shared fetch is complete.
Typical patterns are:
- subscribe to
profilesListand map it into a profile selector UI; - mirror the selected profile into app-owned state;
- pass the chosen profile onward to portfolio and feature-eligibility logic;
- reset or rebuild downstream state when
clearStateis triggered.
Change the package when a new profile family, new upstream endpoint, or new shared grouped state shape is required.
Extension example: derive a selected profile in consumer state
ts
import { getProfiles, profilesBuilder, type IProfilesList } from '@investec/plugins-profiles-builder';
type SelectedProfileState = {
clientType: string;
profileKey: string;
profile: unknown;
};
let selectedProfileState: SelectedProfileState | undefined;
profilesBuilder.authResponse.next(authResponse);
profilesBuilder.profilesList.subscribe((profileList: IProfilesList) => {
const privateClientEntry = profileList.data.find((item) => item.clientType === 'private-client');
if (!privateClientEntry || privateClientEntry.selectedProfile.length === 0) {
return;
}
const wrappedProfile = privateClientEntry.selectedProfile[0];
const profileKey = Object.keys(wrappedProfile)[0];
selectedProfileState = {
clientType: privateClientEntry.clientType,
profileKey,
profile: wrappedProfile[profileKey],
};
});
getProfiles();Extend the shared plugin
Add a new profile family by updating:
- the approved fetch helper in
profiles-builder/src/lib/profiles-builder.ts; - the auth condition in
getProfiles(); - normalisation to the common
nameandidfields; IProfilesEntityand grouped profile types;profilesListclient-type grouping and default selection;- package tests and the public export when new types are supported.
A new API call must preserve the WPaaS: critical header when required and use the approved platform-relative route. Contact the Web Platform team before adding a client type, changing selected-profile semantics, changing profile identity fields, or altering reset and application-lifetime state.
Consumer notes
getProfiles()depends onprofilesBuilder.authResponsebeing set first.clearState.next()resets the cached auth response, profile buckets, and the groupedprofilesList.- The package keeps adding profile families into
profilesListrather than replacing the whole object every time, which is useful for multi-client-type consumers.