Skip to content

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-builder

The 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 name and id
  • legacy typed collections through updateAppState
  • grouped client-type profile state through profilesList

Public contract ​

The main package-root exports include:

  • profilesBuilder
  • getProfiles()
  • direct fetch helpers getZaProfiles(), getIfaProfiles(), and getBusinessBankingProfiles()
  • profile and auth-response types

profilesBuilder contains:

  • activeEnvironment
  • updateAppState
  • authResponse
  • clearState
  • profilesList

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/profiles by 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:

FlagBusiness 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 profilesList and 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 clearState is 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:

  1. the approved fetch helper in profiles-builder/src/lib/profiles-builder.ts;
  2. the auth condition in getProfiles();
  3. normalisation to the common name and id fields;
  4. IProfilesEntity and grouped profile types;
  5. profilesList client-type grouping and default selection;
  6. 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 on profilesBuilder.authResponse being set first.
  • clearState.next() resets the cached auth response, profile buckets, and the grouped profilesList.
  • The package keeps adding profile families into profilesList rather than replacing the whole object every time, which is useful for multi-client-type consumers.