Appearance
Feature library
@investec/plugins-feature-library is the main consumer-facing package for feature discovery. It loads feature records, manages favourites, evaluates requirements, applies Adobe Target overrides, and provides search helpers.
Package
Warning: By default, this package must be installed only by the platform team into the Investec Online shell application. Do not add it as a direct dependency of a consumer/feature application unless the Web Platform team has explicitly approved that specific use as a rare exception. Consumers should use this plugin's behaviour through the Invsy SDK, or contribute a bounded, governed change to this plugin's own source (see Plugin change governance).
sh
npm install --save @investec/plugins-feature-libraryThe platform owns installation of released plugin versions. A consuming team normally contributes shared logic in this repository and then asks the platform team to adopt the published version.
What it owns
- feature-registry fetch helpers;
- favourite add/remove helpers;
- in-memory customer-context caches for auth, portfolio, and platform data;
- requirement evaluation based on auth, portfolio, platform, API checks, and customer exclusions;
- Adobe Target metadata overrides for feature cards;
- fuzzy search helpers through
Fuse.js.
Public contract
The main exports are:
- registry and favourite fetch helpers such as
getWebFeatures(...),getMobileFeatures(...),getFavouriteFeatures(...),addFavouriteFeature(...),removeFavouriteFeature(...) - context setters such as
setFeatureLibraryAuthResponse(...),setFeatureLibraryPortfolio(...),setFeatureLibraryPlatformData(...),setFeatureLibraryClientContext(...) - eligibility helpers such as
checkFeatureRequirements(...),checkFeatureApiRequirements(...),checkExcludedClientFeatures(...) - Adobe Target and search helpers such as
checkAdobeTargetActivities(...),featureSearch(...),featureSearchNoStrict(...)
Feature record shape
The package expects feature entries shaped like:
ts
interface IFeatureApps {
key: string;
value: {
name: string;
permissions: string[];
clientType: string;
discoverable: boolean;
requirements: { location: string; flag: string; condition?: string }[];
apiRequirements: { apiEndpoint?: string; propertyName?: string };
description: { short: string; full: string };
media: { icon: string; thumbnail: string; banner: string; region: string };
tags: string[];
keywords: string[];
route: string;
urlPath: string;
callToAction: { text: string; target: string };
};
}Integration pattern
Load registry data:
ts
import { getWebFeatures, setFeatureLibraryAuthResponse, setFeatureLibraryPortfolio, setFeatureLibraryPlatformData, checkFeatureRequirements } from '@investec/plugins-feature-library';
const features = await getWebFeatures('');
setFeatureLibraryAuthResponse(authResponse);
setFeatureLibraryPortfolio(portfolioData);
setFeatureLibraryPlatformData(platformData);
const visible = features.filter((feature) => checkFeatureRequirements(feature.value.requirements, feature.key));Eligibility model
checkFeatureRequirements(...) combines:
- auth context
- platform data
- portfolio data
- in-memory exclusion results from
checkExcludedClientFeatures(...) - in-memory API requirement results from
checkFeatureApiRequirements(...)
checkFeatureApiRequirements(...) is asynchronous because it performs the feature-specific API calls first. Call it before rendering requirement-sensitive features for a selected profile.
Favourites
Favourites are handled through the shared /api/favourites/... routes:
ts
const favourites = await getFavouriteFeatures('', zetaId);
await addFavouriteFeature('', { clientId: zetaId, featureId: feature.key });
await removeFavouriteFeature('', favouriteId);Adobe Target overrides
If a feature entry contains adobeTargetActivity, use checkAdobeTargetActivities(feature, adobeTargetResponse) before rendering the card. The helper mutates the feature metadata to use content from the matching Target activity.
Search
Use the stricter search helper for normal feature-library search:
ts
const results = featureSearch('card', features);Use featureSearchNoStrict(...) when you intentionally want looser matching, such as "similar features" suggestions.
How consumers extend it
Consumers extend this package by composing around the shared eligibility engine, not by reimplementing it.
Common consumer extensions are:
- pushing additional platform or portfolio context before evaluation;
- deciding when to run
checkFeatureApiRequirements(...)for a selected profile; - filtering or ordering the final visible feature list for a page;
- using Adobe Target overrides for one surface while leaving another unchanged.
Change the package when the shared requirement model itself must change, such as introducing a new requirement source, cache rule, or feature-record contract.
Extension example: build a page-specific feature list
ts
import { checkFeatureApiRequirements, checkFeatureRequirements, featureSearch, getWebFeatures, setFeatureLibraryAuthResponse, setFeatureLibraryPlatformData, setFeatureLibraryPortfolio, type IFeatureApps } from '@investec/plugins-feature-library';
type BuildFeatureLibraryParams = {
authResponse: any;
portfolioData: any;
platformData: { isStaff?: boolean };
profileId?: string;
searchTerm?: string;
};
export async function buildVisibleFeatureCards({ authResponse, portfolioData, platformData, profileId, searchTerm = '' }: BuildFeatureLibraryParams): Promise<IFeatureApps[]> {
const allFeatures = await getWebFeatures('');
setFeatureLibraryAuthResponse(authResponse);
setFeatureLibraryPortfolio(portfolioData);
setFeatureLibraryPlatformData(platformData);
await checkFeatureApiRequirements(allFeatures, profileId);
const source = searchTerm ? featureSearch(searchTerm, allFeatures) : allFeatures;
return source.filter((feature) => feature.value.discoverable && checkFeatureRequirements(feature.value.requirements, feature.key));
}Extend the shared plugin
| Change | Location |
|---|---|
| Add a feature-registry or favourites API helper | feature-library/src/lib/shared/api-calls.ts |
| Add an eligibility source or shared rule | feature-library/src/lib/feature-library.ts |
| Extend the feature or favourite record contract | feature-library/src/lib/types/feature-apps.interface.ts |
| Add reusable object or search utilities | feature-library/src/lib/utilities.ts |
| Publish the supported addition | feature-library/src/index.ts |
For a new API helper, accept the base URL or use the existing platform-relative route pattern, add explicit request and response types, check unsuccessful HTTP responses, and test success and failure with synthetic data.
Contact the Web Platform team before changing eligibility semantics, cache lifecycle, customer exclusions, registry record meaning, favourites ownership, or platform authorisation assumptions.
Consumer notes
- This package keeps several module-level caches in memory for the lifetime of the application.
checkFeatureRequirements(...)is synchronous only after the relevant context and API requirement state have already been loaded.- Exclusion and API-requirement results are additive caches, so consumers should avoid reusing stale application state across logout boundaries without a full app reset.