@microsoft/1ds-core-js
Version:
Microsoft Application Insights JavaScript SDK - 1ds-core-js
397 lines • 17.9 kB
JavaScript
/*
* 1DS JS SDK Core, 4.3.9
* Copyright (c) Microsoft and contributors. All rights reserved.
* (Microsoft Internal Only)
*/
var _a;
/**
* Utils.ts
* @author Abhilash Panwar (abpanwar) Hector Hernandez (hectorh)
* @copyright Microsoft 2018
* File containing utility functions.
*/
import { arrForEach, getGlobalInst, getNavigator, hasDocument, hasWindow, isArray, isBoolean, isNullOrUndefined, isNumber, isObject, isReactNative, isString, isUndefined, newGuid, objForEachKey, perfNow } from "@microsoft/applicationinsights-core-js";
import { ObjProto, strShimObject } from "@microsoft/applicationinsights-shims";
import { strIndexOf, strLeft } from "@nevware21/ts-utils";
import { STR_EMPTY } from "./InternalConstants";
import { _DYN_INDEX_OF, _DYN_LENGTH, _DYN_PROCESS_TELEMETRY_ST0, _DYN_TIMINGS, _DYN_VALUE } from "./__DynamicConstants";
export var Version = '4.3.9';
export var FullVersionString = "1DS-Web-JS-" + Version;
var ObjHasOwnProperty = ObjProto.hasOwnProperty;
// Defining here so we don't need to take (import) the ApplicationInsights Common module
var strDisabledPropertyName = "Microsoft_ApplicationInsights_BypassAjaxInstrumentation";
var strWithCredentials = "withCredentials";
var strTimeout = "timeout";
// If value is array just get the type for the first element
var _fieldTypeEventPropMap = (_a = {},
_a[0 /* FieldValueSanitizerType.NotSet */] = 0 /* eEventPropertyType.Unspecified */,
_a[2 /* FieldValueSanitizerType.Number */] = 6 /* eEventPropertyType.Double */,
_a[1 /* FieldValueSanitizerType.String */] = 1 /* eEventPropertyType.String */,
_a[3 /* FieldValueSanitizerType.Boolean */] = 7 /* eEventPropertyType.Bool */,
_a[4096 /* FieldValueSanitizerType.Array */ | 2 /* FieldValueSanitizerType.Number */] = 6 /* eEventPropertyType.Double */,
_a[4096 /* FieldValueSanitizerType.Array */ | 1 /* FieldValueSanitizerType.String */] = 1 /* eEventPropertyType.String */,
_a[4096 /* FieldValueSanitizerType.Array */ | 3 /* FieldValueSanitizerType.Boolean */] = 7 /* eEventPropertyType.Bool */,
_a);
/**
* @ignore
*/
// let _uaDisallowsSameSiteNone = null;
var uInt8ArraySupported = null;
// var _areCookiesAvailable: boolean | undefined;
/**
* Checks if document object is available
*/
export var isDocumentObjectAvailable = hasDocument();
/**
* Checks if window object is available
*/
export var isWindowObjectAvailable = hasWindow();
/**
* Checks if value is assigned to the given param.
* @param value - The token from which the tenant id is to be extracted.
* @returns True/false denoting if value is assigned to the param.
*/
export function isValueAssigned(value) {
/// <summary> takes a value and checks for undefined, null and empty string </summary>
/// <param type="any"> value to be tested </param>
/// <returns> true if value is null undefined or emptyString </returns>
return !(value === STR_EMPTY || isNullOrUndefined(value));
}
/**
* Gets the tenant id from the tenant token.
* @param apiKey - The token from which the tenant id is to be extracted.
* @returns The tenant id.
*/
export function getTenantId(apiKey) {
if (apiKey) {
var indexTenantId = strIndexOf(apiKey, "-");
if (indexTenantId > -1) {
return strLeft(apiKey, indexTenantId);
}
}
return STR_EMPTY;
}
/**
* Checks if Uint8Array are available in the current environment. Safari and Firefox along with
* ReactNative are known to not support Uint8Array properly.
* @returns True if available, false otherwise.
*/
export function isUint8ArrayAvailable() {
if (uInt8ArraySupported === null) {
uInt8ArraySupported = !isUndefined(Uint8Array) && !isSafariOrFirefox() && !isReactNative();
}
return uInt8ArraySupported;
}
/**
* Checks if the value is a valid EventLatency.
* @param value - The value that needs to be checked.
* @returns True if the value is in AWTEventLatency, false otherwise.
*/
export function isLatency(value) {
if (value && isNumber(value) && value >= 1 /* EventLatencyValue.Normal */ && value <= 4 /* EventLatencyValue.Immediate */) {
return true;
}
return false;
}
/**
* Sanitizes the Property. It checks the that the property name and value are valid. It also
* checks/populates the correct type and pii of the property value.
* @param name - property name - The property name.
* @param property - The property value or an IEventProperty containing value,
* type ,pii and customer content.
* @returns IEventProperty containing valid name, value, pii and type or null if invalid.
*/
export function sanitizeProperty(name, property, stringifyObjects) {
// Check that property is valid
if ((!property && !isValueAssigned(property)) || typeof name !== "string") {
return null;
}
// Perf optimization -- only need to get the type once not multiple times
var propType = typeof property;
// If the property isn't IEventProperty (and is either string, number, boolean or array), convert it into one.
if (propType === "string" || propType === "number" || propType === "boolean" || isArray(property)) {
property = { value: property };
}
else if (propType === "object" && !ObjHasOwnProperty.call(property, "value")) {
property = { value: stringifyObjects ? JSON.stringify(property) : property };
}
else if (isNullOrUndefined(property[_DYN_VALUE /* @min:%2evalue */])
|| property[_DYN_VALUE /* @min:%2evalue */] === STR_EMPTY || (!isString(property[_DYN_VALUE /* @min:%2evalue */])
&& !isNumber(property[_DYN_VALUE /* @min:%2evalue */]) && !isBoolean(property[_DYN_VALUE /* @min:%2evalue */])
&& !isArray(property[_DYN_VALUE /* @min:%2evalue */]))) {
// Since property is IEventProperty, we need to validate its value
return null;
}
// We need to check that if the property value is an array, it is valid
if (isArray(property[_DYN_VALUE /* @min:%2evalue */]) &&
!isArrayValid(property[_DYN_VALUE /* @min:%2evalue */])) {
return null;
}
// If either pii or cc is set convert value to string (since only string pii/cc is allowed).
// If the value is a complex type like an array that can't be converted to string we will drop
// the property.
if (!isNullOrUndefined(property.kind)) {
if (isArray(property[_DYN_VALUE /* @min:%2evalue */]) || !isValueKind(property.kind)) {
return null;
}
property[_DYN_VALUE /* @min:%2evalue */] = property[_DYN_VALUE /* @min:%2evalue */].toString();
}
return property;
}
export function getCommonSchemaMetaData(value, kind, type) {
var encodedTypeValue = -1;
if (!isUndefined(value)) {
if (kind > 0) {
if (kind === 32 /* eValueKind.CustomerContent_GenericContent */) {
// encode customer content. Value can only be string. bit 13-16 are for cc
encodedTypeValue = (1 << 13);
}
else if (kind <= 13) {
// encode PII. Value can only be string. bits 5-12 are for Pii
encodedTypeValue = (kind << 5);
}
}
// isDataType checks that the "type" is a number so we don't need to check for undefined
if (isDataType(type)) {
// Data Type is provided and valid, so use that
if (encodedTypeValue === -1) {
// Don't return -1
encodedTypeValue = 0;
}
encodedTypeValue |= type;
}
else {
var propType = _fieldTypeEventPropMap[getFieldValueType(value)] || -1;
if (encodedTypeValue !== -1 && propType !== -1) {
// pii exists so we must return correct type
encodedTypeValue |= propType;
}
else if (propType === 6 /* eEventPropertyType.Double */) {
encodedTypeValue = propType;
}
}
}
return encodedTypeValue;
}
/**
* Helper to get and decode the cookie value using decodeURIComponent, this is for historical
* backward compatibility where the document.cookie value was decoded before parsing.
* @param cookieMgr - The cookie manager to use
* @param name - The name of the cookie to get
* @param decode - A flag to indicate whether the cookie value should be decoded
* @returns The decoded cookie value (if available) otherwise an empty string.
*/
export function getCookieValue(cookieMgr, name, decode) {
if (decode === void 0) { decode = true; }
var cookieValue;
if (cookieMgr) {
cookieValue = cookieMgr.get(name);
if (decode && cookieValue && decodeURIComponent) {
cookieValue = decodeURIComponent(cookieValue);
}
}
return cookieValue || STR_EMPTY;
}
/**
* Create a new guid.
* @param style - The style of guid to generated, defaults to Digits
* Digits (Default) : 32 digits separated by hyphens: 00000000-0000-0000-0000-000000000000
* Braces - 32 digits separated by hyphens, enclosed in braces: \{00000000-0000-0000-0000-000000000000\}
* Parentheses - 32 digits separated by hyphens, enclosed in parentheses: (00000000-0000-0000-0000-000000000000)
* Numeric - 32 digits: 00000000000000000000000000000000
*/
export function createGuid(style) {
if (style === void 0) { style = "D" /* GuidStyle.Digits */; }
var theGuid = newGuid();
if (style === "B" /* GuidStyle.Braces */) {
theGuid = "{" + theGuid + "}";
}
else if (style === "P" /* GuidStyle.Parentheses */) {
theGuid = "(" + theGuid + ")";
}
else if (style === "N" /* GuidStyle.Numeric */) {
theGuid = theGuid.replace(/-/g, STR_EMPTY);
}
return theGuid;
}
/**
* Pass in the objects to merge as arguments.
* @param obj1 - object to merge. Set this argument to 'true' for a deep extend.
* @param obj2 - object to merge.
* @param obj3 - object to merge.
* @param obj4 - object to merge.
* @param obj5 - object to merge.
* @returns The extended object.
*/
export function extend(obj, obj2, obj3, obj4, obj5) {
// Variables
var extended = {};
var deep = false;
var i = 0;
var length = arguments[_DYN_LENGTH /* @min:%2elength */];
var theArgs = arguments;
// Check if a deep merge
if (isBoolean(theArgs[0])) {
deep = theArgs[0];
i++;
}
// Loop through each object and conduct a merge
for (; i < length; i++) {
var obj = theArgs[i];
objForEachKey(obj, function (prop, value) {
// If deep merge and property is an object, merge properties
if (deep && value && isObject(value)) {
if (isArray(value)) {
extended[prop] = extended[prop] || [];
arrForEach(value, function (arrayValue, arrayIndex) {
if (arrayValue && isObject(arrayValue)) {
extended[prop][arrayIndex] = extend(true, extended[prop][arrayIndex], arrayValue);
}
else {
extended[prop][arrayIndex] = arrayValue;
}
});
}
else {
extended[prop] = extend(true, extended[prop], value);
}
}
else {
extended[prop] = value;
}
});
}
return extended;
}
export var getTime = perfNow;
export function isValueKind(value) {
// Always assume that it's a number (no type checking) for performance as this is used during the JSON serialization
if (value === 0 /* eValueKind.NotSet */ || ((value > 0 /* eValueKind.NotSet */ && value <= 13 /* eValueKind.Pii_IPV4AddressLegacy */) || value === 32 /* eValueKind.CustomerContent_GenericContent */)) {
return true;
}
return false;
}
function isDataType(value) {
// Remark: 0 returns false, but it doesn't affect encoding anyways
// Always assume that it's a number (no type checking) for performance as this is used during the JSON serialization
if (value >= 0 && value <= 9) {
return true;
}
return false;
}
function isSafariOrFirefox() {
var nav = getNavigator();
// If non-browser navigator will be undefined
if (!isUndefined(nav) && nav.userAgent) {
var ua = nav.userAgent.toLowerCase();
if ((ua[_DYN_INDEX_OF /* @min:%2eindexOf */]("safari") >= 0 || ua[_DYN_INDEX_OF /* @min:%2eindexOf */]("firefox") >= 0) && ua[_DYN_INDEX_OF /* @min:%2eindexOf */]("chrome") < 0) {
return true;
}
}
return false;
}
export function isArrayValid(value) {
return value[_DYN_LENGTH /* @min:%2elength */] > 0;
}
export function setProcessTelemetryTimings(event, identifier) {
var evt = event;
evt[_DYN_TIMINGS /* @min:%2etimings */] = evt[_DYN_TIMINGS /* @min:%2etimings */] || {};
evt[_DYN_TIMINGS /* @min:%2etimings */][_DYN_PROCESS_TELEMETRY_ST0 /* @min:%2eprocessTelemetryStart */] = evt[_DYN_TIMINGS /* @min:%2etimings */][_DYN_PROCESS_TELEMETRY_ST0 /* @min:%2eprocessTelemetryStart */] || {};
evt[_DYN_TIMINGS /* @min:%2etimings */][_DYN_PROCESS_TELEMETRY_ST0 /* @min:%2eprocessTelemetryStart */][identifier] = getTime();
}
/**
* Returns a bitwise value for the FieldValueSanitizerType enum representing the decoded type of the passed value
* @param value - The value to determine the type
*/
export function getFieldValueType(value) {
var theType = 0 /* FieldValueSanitizerType.NotSet */;
if (value !== null && value !== undefined) {
var objType = typeof value;
if (objType === "string") {
theType = 1 /* FieldValueSanitizerType.String */;
}
else if (objType === "number") {
theType = 2 /* FieldValueSanitizerType.Number */;
}
else if (objType === "boolean") {
theType = 3 /* FieldValueSanitizerType.Boolean */;
}
else if (objType === strShimObject) {
theType = 4 /* FieldValueSanitizerType.Object */;
if (isArray(value)) {
theType = 4096 /* FieldValueSanitizerType.Array */;
if (value[_DYN_LENGTH /* @min:%2elength */] > 0) {
// Empty arrays are not supported and are considered to be the same as null
theType |= getFieldValueType(value[0]);
}
}
else if (ObjHasOwnProperty.call(value, "value")) {
// Looks like an IEventProperty
theType = 8192 /* FieldValueSanitizerType.EventProperty */ | getFieldValueType(value[_DYN_VALUE /* @min:%2evalue */]);
}
}
}
return theType;
}
/**
* Helper to identify whether we are running in a chromium based browser environment
*/
export function isChromium() {
return !!getGlobalInst("chrome");
}
/**
* Create and open an XMLHttpRequest object
* @param method - The request method
* @param urlString - The url
* @param withCredentials - Option flag indicating that credentials should be sent
* @param disabled - Optional flag indicating that the XHR object should be marked as disabled and not tracked (default is false)
* @param isSync - Optional flag indicating if the instance should be a synchronous request (defaults to false)
* @param timeout - Optional value identifying the timeout value that should be assigned to the XHR request
* @returns A new opened XHR request
*/
export function openXhr(method, urlString, withCredentials, disabled, isSync, timeout) {
if (disabled === void 0) { disabled = false; }
if (isSync === void 0) { isSync = false; }
function _wrapSetXhrProp(xhr, prop, value) {
try {
xhr[prop] = value;
}
catch (e) {
// - Wrapping as depending on the environment setting the property may fail (non-terminally)
}
}
var xhr = new XMLHttpRequest();
if (disabled) {
// Tag the instance so it's not tracked (trackDependency)
// If the environment has locked down the XMLHttpRequest (preventExtensions and/or freeze), this would
// cause the request to fail and we no telemetry would be sent
_wrapSetXhrProp(xhr, strDisabledPropertyName, disabled);
}
if (withCredentials) {
// Some libraries require that the withCredentials flag is set "before" open and
// - Wrapping as IE 10 has started throwing when setting before open
_wrapSetXhrProp(xhr, strWithCredentials, withCredentials);
}
xhr.open(method, urlString, !isSync);
if (withCredentials) {
// withCredentials should be set AFTER open (https://xhr.spec.whatwg.org/#the-withcredentials-attribute)
// And older firefox instances from 11+ will throw for sync events (current versions don't) which happens during unload processing
_wrapSetXhrProp(xhr, strWithCredentials, withCredentials);
}
// Only set the timeout for asynchronous requests as
// "Timeout shouldn't be used for synchronous XMLHttpRequests requests used in a document environment or it will throw an InvalidAccessError exception.""
// https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/timeout
if (!isSync && timeout) {
_wrapSetXhrProp(xhr, strTimeout, timeout);
}
return xhr;
}
/**
* Check to see if the value is \> 0
* @param value - The value to check
* @returns true if \> 0 otherwise false
*/
export function isGreaterThanZero(value) {
return value > 0;
}
//# sourceMappingURL=Utils.js.map