@amplitude/analytics-browser
Version:
Official Amplitude SDK for Web
162 lines • 8.57 kB
JavaScript
import { __assign, __values } from "tslib";
/**
* Performs a deep transformation of a remote config object so that
* it matches the expected schema of the local config.
*
* Specifically, it normalizes nested `enabled` flags into concise union types.
*
* ### Transformation Rules:
* - If an object has `enabled: true`, it is replaced by the same object without the `enabled` field.
* - If it has only `enabled: true`, it is replaced with `true`.
* - If it has `enabled: false`, it is replaced with `false` regardless of other fields.
*
* ### Examples:
* Input: { prop: { enabled: true, hello: 'world' }}
* Output: { prop: { hello: 'world' } }
*
* Input: { prop: { enabled: true }}
* Output: { prop: true }
*
* Input: { prop: { enabled: false, hello: 'world' }}
* Output: { prop: false }
*
* Input: { prop: { hello: 'world' }}
* Output: { prop: { hello: 'world' } } // No change
*
* @param config Remote config object to be transformed
* @returns Transformed config object compatible with local schema
*/
export function translateRemoteConfigToLocal(config) {
var e_1, _a;
// Disabling type checking rules because remote config comes from a remote source
// and this function needs to handle any unexpected values
/* eslint-disable @typescript-eslint/no-unsafe-member-access,
@typescript-eslint/no-unsafe-assignment,
@typescript-eslint/no-unsafe-argument
*/
if (typeof config !== 'object' || config === null) {
return;
}
// translations are not applied on array properties
if (Array.isArray(config)) {
return;
}
var propertyNames = Object.keys(config);
try {
for (var propertyNames_1 = __values(propertyNames), propertyNames_1_1 = propertyNames_1.next(); !propertyNames_1_1.done; propertyNames_1_1 = propertyNames_1.next()) {
var propertyName = propertyNames_1_1.value;
try {
var value = config[propertyName];
// transform objects with { enabled } property to boolean | object
if (typeof (value === null || value === void 0 ? void 0 : value.enabled) === 'boolean') {
if (value.enabled) {
// if enabled is true, set the value to the rest of the object
// or true if the object has no other properties
delete value.enabled;
if (Object.keys(value).length === 0) {
config[propertyName] = true;
}
}
else {
// If enabled is false, set the value to false
config[propertyName] = false;
}
}
// recursively translate properties of the value
translateRemoteConfigToLocal(value);
}
catch (e) {
// a failure here means that an accessor threw an error
// so don't translate it
// TODO(diagnostics): add a diagnostic event for this
}
}
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try {
if (propertyNames_1_1 && !propertyNames_1_1.done && (_a = propertyNames_1.return)) _a.call(propertyNames_1);
}
finally { if (e_1) throw e_1.error; }
}
}
/**
* Updates the browser config in place by applying remote configuration settings.
* Primarily merges autocapture settings from the remote config into the browser config.
*
* @param remoteConfig - The remote configuration to apply, or null if none available
* @param browserConfig - The browser config object to update (modified in place)
*/
export function updateBrowserConfigWithRemoteConfig(remoteConfig, browserConfig) {
var e_2, _a;
var _b, _c;
if (!remoteConfig) {
return;
}
// translate remote config to local compatible format
translateRemoteConfigToLocal(remoteConfig);
try {
browserConfig.loggerProvider.debug('Update browser config with remote configuration:', JSON.stringify(remoteConfig));
// type cast error will be thrown if remoteConfig is not a valid RemoteConfigBrowserSDK
// and it will be caught by the try-catch block
var typedRemoteConfig = remoteConfig;
// merge remoteConfig.autocapture and browserConfig.autocapture
// if a field is in remoteConfig.autocapture, use that value
// if a field is not in remoteConfig.autocapture, use the value from browserConfig.autocapture
if (typedRemoteConfig && 'autocapture' in typedRemoteConfig) {
if (typeof typedRemoteConfig.autocapture === 'boolean') {
browserConfig.autocapture = typedRemoteConfig.autocapture;
}
if (typeof typedRemoteConfig.autocapture === 'object' && typedRemoteConfig.autocapture !== null) {
var transformedAutocaptureRemoteConfig = __assign({}, typedRemoteConfig.autocapture);
if (browserConfig.autocapture === undefined) {
browserConfig.autocapture = typedRemoteConfig.autocapture;
}
// Handle Element Interactions config initialization
if (typeof typedRemoteConfig.autocapture.elementInteractions === 'object' &&
typedRemoteConfig.autocapture.elementInteractions !== null &&
((_b = typedRemoteConfig.autocapture.elementInteractions.pageUrlAllowlistRegex) === null || _b === void 0 ? void 0 : _b.length)) {
transformedAutocaptureRemoteConfig.elementInteractions = __assign({}, typedRemoteConfig.autocapture.elementInteractions);
var transformedRcElementInteractions = transformedAutocaptureRemoteConfig.elementInteractions;
var exactAllowList = (_c = transformedRcElementInteractions.pageUrlAllowlist) !== null && _c !== void 0 ? _c : [];
// Convert string patterns to RegExp objects, warn on invalid patterns and skip them
var regexList = [];
try {
for (var _d = __values(typedRemoteConfig.autocapture.elementInteractions.pageUrlAllowlistRegex), _e = _d.next(); !_e.done; _e = _d.next()) {
var pattern = _e.value;
try {
regexList.push(new RegExp(pattern));
}
catch (regexError) {
browserConfig.loggerProvider.warn("Invalid regex pattern: ".concat(pattern), regexError);
}
}
}
catch (e_2_1) { e_2 = { error: e_2_1 }; }
finally {
try {
if (_e && !_e.done && (_a = _d.return)) _a.call(_d);
}
finally { if (e_2) throw e_2.error; }
}
var combinedPageUrlAllowlist = exactAllowList.concat(regexList);
transformedRcElementInteractions.pageUrlAllowlist = combinedPageUrlAllowlist;
delete transformedRcElementInteractions.pageUrlAllowlistRegex;
}
if (typeof browserConfig.autocapture === 'boolean') {
browserConfig.autocapture = __assign({ attribution: browserConfig.autocapture, fileDownloads: browserConfig.autocapture, formInteractions: browserConfig.autocapture, pageViews: browserConfig.autocapture, sessions: browserConfig.autocapture, elementInteractions: browserConfig.autocapture, webVitals: browserConfig.autocapture, frustrationInteractions: browserConfig.autocapture }, transformedAutocaptureRemoteConfig);
}
if (typeof browserConfig.autocapture === 'object') {
browserConfig.autocapture = __assign(__assign({}, browserConfig.autocapture), transformedAutocaptureRemoteConfig);
}
}
// Override default tracking options if autocapture is updated by remote config
browserConfig.defaultTracking = browserConfig.autocapture;
}
browserConfig.loggerProvider.debug('Browser config after remote config update:', JSON.stringify(browserConfig));
}
catch (e) {
browserConfig.loggerProvider.error('Failed to apply remote configuration because of error: ', e);
}
}
//# sourceMappingURL=joined-config.js.map