@applicaster/zapp-react-dom-app
Version:
Zapp App Component for Applicaster's Quick Brick React Native App
175 lines (144 loc) • 4.51 kB
text/typescript
/* eslint-disable max-len */
import * as R from "ramda";
import {
ANALYTICS_CORE_EVENTS,
GENERAL_PARAMETERS,
} from "@applicaster/zapp-react-native-utils/analyticsUtils/events";
import type { GeneralParameters } from "@applicaster/zapp-react-native-utils/analyticsUtils/events";
import {
log_debug,
log_error,
log_warning,
} from "@applicaster/zapp-react-native-utils/analyticsUtils/logger";
import { isEmptyOrNil } from "@applicaster/zapp-react-native-utils/cellUtils";
import { QuickBrickCommunicationModule } from "../QuickBrickCommunicationModule";
export const getFromStorage = (key) => {
const DEFAULT_NAMESPACE = "applicaster.v2";
const NAMESPACE_SEPARATOR = "_::_";
const namespace = `${DEFAULT_NAMESPACE}${NAMESPACE_SEPARATOR}`;
const storageKey = `${namespace}${key}`;
// the browser storage API is synchronous vs our storage API which is async
return sessionStorage.getItem(storageKey) || localStorage.getItem(storageKey);
};
export const prepareEventPayload = (): GeneralParameters | {} => {
if (!QuickBrickCommunicationModule) {
log_warning(
"Failed to prepare event payload, 'QuickBrickCommunicationModule' is missing"
);
return {};
}
const {
buildVersion,
bundleIdentifier,
quickBrickVersion,
riversConfigurationId,
sdkVersion,
versionName,
platform,
} = QuickBrickCommunicationModule as Partial<QBCommunicationModule>;
const buildtimeData = {
build_number: buildVersion,
bundle_id: bundleIdentifier,
quickbrick_version: quickBrickVersion,
layout_id: riversConfigurationId,
sdk_version: sdkVersion,
version: versionName,
zapp_platform: platform,
};
const runtimeData = {
uuid: getFromStorage("uuid"),
layout_id: getFromStorage("layoutId"),
};
const requiredKeys = Object.keys(GENERAL_PARAMETERS);
const eventPayload: GeneralParameters | {} = {};
const missingKeys: string[] = [];
try {
requiredKeys.forEach((key) => {
const keyName = GENERAL_PARAMETERS[key];
const value = runtimeData[keyName] || buildtimeData[keyName];
if (value) {
eventPayload[keyName] = value;
} else {
missingKeys.push(keyName);
}
});
} catch (e) {
log_error("There was an error preparing analytics event payload", e);
}
if (missingKeys.length > 0) {
log_warning("Analytics event payload is missing required keys", {
missingKeys,
});
}
return eventPayload;
};
function isInvalidAnalyticsData(eventName, payload = null) {
const isInvalid = isEmptyOrNil(eventName);
if (isInvalid) {
log_debug(
"AnalyticsBridge received an event invalid data. Event will not be emitted",
{ eventName, payload }
);
return true;
}
return false;
}
export const AnalyticsBridge = (function () {
let registeredAnalyticPlugins: {
module: {
sendEvent: Function;
initialize?: Function;
getPlayerConfiguration?: Function;
};
configuration?: any;
}[] = [];
const startTime = {};
const endTime = {};
return {
postEvent: function (eventName, payload) {
if (isInvalidAnalyticsData(eventName, payload)) {
return;
}
const updatedPayload = {
...prepareEventPayload(),
...payload,
};
registeredAnalyticPlugins.forEach((plugin) => {
plugin.module.sendEvent(eventName, updatedPayload);
});
},
endTimedEvent: function (eventName, payload) {
endTime[eventName] = new Date();
const toSeconds = (ms) => ms / 1000;
const duration = startTime[eventName]
? toSeconds(endTime[eventName] - startTime[eventName])
: "N/A";
if (isInvalidAnalyticsData(eventName, payload)) {
return;
}
const updatedPayload = {
duration,
...prepareEventPayload(),
...payload,
};
registeredAnalyticPlugins.forEach((plugin) => {
plugin.module.sendEvent(
ANALYTICS_CORE_EVENTS.TIME_ON_SCREEN,
updatedPayload
);
});
},
postTimedEvent: function (eventName) {
startTime[eventName] = new Date();
},
setPlugins: function (plugins, configs, callbackAfterInitilaize) {
registeredAnalyticPlugins = plugins;
plugins.forEach((plugin) => {
return R.path(["module", "initialize"], plugin)
? plugin.module.initialize(plugin.configuration || {})
: null;
});
callbackAfterInitilaize();
},
};
})();