UNPKG

@microsoft/1ds-core-js

Version:

Microsoft Application Insights JavaScript SDK - 1ds-core-js

397 lines 17.9 kB
/* * 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