pcf-scripts
Version:
This package contains a module for building PowerApps Component Framework (PCF) controls. See project homepage how to install.
118 lines (116 loc) • 5.49 kB
JavaScript
;
/*
* Copyright (c) Microsoft Corporation. All rights reserved.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.composeAutomationAgentString = composeAutomationAgentString;
exports.isSupportedAgentProductVersion = isSupportedAgentProductVersion;
exports.tryParseAutomationAgentStringProductNameVersion = tryParseAutomationAgentStringProductNameVersion;
exports.parseBooleanEnvironmentVariable = parseBooleanEnvironmentVariable;
exports.createCommonAppStartProperties = createCommonAppStartProperties;
const TelemetryConstants = require("./TelemetryConstants");
const MaxAutomationAgentLength = 64;
// This is a limited char set than is supported with HTTP User-Agent for now, as in practice, most symbols aren't used for user agents.
// However, we do want to allow for using package names (nuget, npm, etc), .net assembly names, etc.
const ProductNameRegex = /^[a-zA-Z0-9.+_-]+$/;
const SystemVersionRegex = /^\d+(\.\d+){1,3}$/;
function composeAutomationAgentString(productName, productVersion) {
if (!productName)
throw new Error("productName must be specified.");
if (!productVersion)
throw new Error("productVersion must be specified.");
if (!ProductNameRegex.test(productName)) {
throw new Error(`productName '${productName}' is invalid; only the following characters are allowed: letters, numbers, and the symbols '.', '+', '_', '-'.`);
}
if (!isSupportedAgentProductVersion(productVersion)) {
throw new Error(`productVersion '${productVersion}' is invalid; it should be a valid System.Version or SemVer (v2).`);
}
return `${productName}/${productVersion}`;
}
function isSupportedAgentProductVersion(productVersion) {
if (productVersion) {
// For simplicity, we ignore all content after the SemVer pre-release tag (-) or build metadata (+)
const idxPreRelease = productVersion.indexOf("-");
const idxMetadata = productVersion.indexOf("+");
const idxPreReleaseOrMetadata = idxPreRelease < 0 ? idxMetadata : idxMetadata < 0 ? idxPreRelease : Math.min(idxPreRelease, idxMetadata);
const versionSubStr = idxPreReleaseOrMetadata === -1 ? productVersion : productVersion.substring(0, idxPreReleaseOrMetadata);
return versionSubStr.length >= 1 && SystemVersionRegex.test(versionSubStr);
}
return false;
}
function tryParseAutomationAgentStringProductNameVersion(agent) {
if (!agent)
throw new Error("agent must be specified.");
const firstProduct = agent.split(" ", 2)[0];
if (firstProduct.length > MaxAutomationAgentLength) {
return {
success: false,
invalidReason: `The first product (name and version) has a length of ${firstProduct.length} which is longer than allowed length of ${MaxAutomationAgentLength}.`,
};
}
const parts = firstProduct.split("/");
if (parts.length !== 2) {
// both parts are required
return {
success: false,
invalidReason: "Missing '/' character.",
};
}
const productName = parts[0];
if (!productName || !ProductNameRegex.test(productName)) {
return {
success: false,
invalidReason: "Product name is empty or contains characters other than alpha-numeric and '.', '+', '_', '-'.",
};
}
const productVersion = parts[1];
if (!isSupportedAgentProductVersion(productVersion)) {
return {
success: false,
invalidReason: "Product version is empty or is not a valid System.Version or SemVer (v2).",
};
}
return {
success: true,
firstProductName: productName,
firstProductVersion: productVersion,
};
}
function validateAndSanitizeAutomationAgent(environment) {
if (!environment.automationAgent) {
return undefined;
}
const result = tryParseAutomationAgentStringProductNameVersion(environment.automationAgent);
if (result.success !== true) {
// We throw here because otherwise this corrupts our ability to have accurate telemetry based on automationAgent
throw new Error(`[AppTelemetryConfigurationException] The automationAgent '${environment.automationAgent}' is invalid. ${result.invalidReason} This exception should be considered a developer bug of the calling agent.`);
}
let agent = environment.automationAgent;
// We want to limit open-ended values which could come outside our system.
// Try shortening it to just the first product/version if it's original text is too long
if (agent.length > MaxAutomationAgentLength) {
// we add a comment to indicate in telemetry that it's truncated. This is per the HTTP spec
agent = composeAutomationAgentString(result.firstProductName, result.firstProductVersion) + " --truncated--";
}
return agent;
}
function parseBooleanEnvironmentVariable(value) {
if (value) {
if (value === "1" || value.toUpperCase() === "TRUE") {
return true;
}
if (value === "0" || value.toUpperCase() === "FALSE") {
return false;
}
}
return undefined;
}
function createCommonAppStartProperties(environment) {
const properties = {};
const agent = validateAndSanitizeAutomationAgent(environment);
if (agent) {
properties[TelemetryConstants.PropertyNames.automationAgent] = agent;
}
return properties;
}
//# sourceMappingURL=AppTelemetryUtility.js.map