@microsoft/windows-admin-center-sdk
Version:
Microsoft - Windows Admin Center Shell
961 lines (959 loc) • 38.3 kB
JavaScript
import { LogLevel } from '../diagnostics/log-level';
import { Logging } from '../diagnostics/logging';
/**
* The type of entry point.
*/
export var EnvironmentModuleEntryPointType;
(function (EnvironmentModuleEntryPointType) {
EnvironmentModuleEntryPointType["ConnectionProvider"] = "connectionProvider";
EnvironmentModuleEntryPointType["Solution"] = "solution";
EnvironmentModuleEntryPointType["Tool"] = "tool";
EnvironmentModuleEntryPointType["Service"] = "service";
EnvironmentModuleEntryPointType["SettingsForm"] = "settingsForm";
EnvironmentModuleEntryPointType["GroupProvider"] = "groupProvider";
EnvironmentModuleEntryPointType["Worker"] = "worker";
EnvironmentModuleEntryPointType["Dialog"] = "dialog";
EnvironmentModuleEntryPointType["SnapIn"] = "snapIn";
})(EnvironmentModuleEntryPointType || (EnvironmentModuleEntryPointType = {}));
/**
* The type of lifetime to implement when creating a worker
*/
export var ExtensionTargetType;
(function (ExtensionTargetType) {
ExtensionTargetType["WorkerTarget"] = "workerTarget";
})(ExtensionTargetType || (ExtensionTargetType = {}));
/**
* The state definition of Tool condition.
*/
export var EnvironmentModuleToolState;
(function (EnvironmentModuleToolState) {
/**
* Tool is available on the connection.
*/
EnvironmentModuleToolState[EnvironmentModuleToolState["Available"] = 0] = "Available";
/**
* Tool is not available because it's not configured properly.
*/
EnvironmentModuleToolState[EnvironmentModuleToolState["NotConfigured"] = 1] = "NotConfigured";
/**
* Tool it not supported on the connection.
*/
EnvironmentModuleToolState[EnvironmentModuleToolState["NotSupported"] = 2] = "NotSupported";
})(EnvironmentModuleToolState || (EnvironmentModuleToolState = {}));
export const defaultEnvironmentConfiguration = {
gateway: {
disabled: false
},
appBar: {
title: {
hide: false
},
solution: {
hide: false,
hideDropdown: false
},
navigation: {
allowHistory: false,
allowRefresh: false,
allowUrlInput: false,
allowHome: false
},
urlField: {
hideSolutionUrl: true
},
rightMenu: {
showScripts: true,
showSettings: true,
showAbout: true,
showWindowControls: false,
showShareLink: false
},
aboutDialog: {
showFeedback: true,
feedbackLink: 'https://go.microsoft.com/fwlink/?linkid=2033442',
showDocumentation: true,
documentationLink: 'https://go.microsoft.com/fwlink/?linkid=2150525',
releaseNotesLink: 'https://aka.ms/honolulucurrent',
seeMoreReleaseDetailsLink: 'https://go.microsoft.com/fwlink/?linkid=2152971',
showLicense: true,
showScriptsUseRights: true,
showLicenseExtensions: true,
showPrivacyStatement: true,
privacyLink: 'https://aka.ms/winserverprivacy',
showSupportPolicy: true,
supportLink: 'https://aka.ms/wac-support-policy',
showThirdPartyNotice: true,
showShortcuts: true,
openLinkWithoutHref: false,
showAccessibilityCompliance: false,
accessibilityComplianceLink: 'https://go.microsoft.com/fwlink/?linkid=2121429'
},
overview: {
gatewayStatusUpdateLink: 'settings/updates',
updateLearnMoreLink: 'https://aka.ms/honolulucurrent'
}
},
extensionsAutoUpdate: {
enable: true,
showAlert: true
},
gatewayAutoUpdate: {
enable: true
},
whatsNew: {
showDialog: true
},
tools: {
hide: false
},
connections: {
type: 'standard',
header: {
hide: false
}
},
telemetry: {
sourceLibraryCdnLink: 'https://js.monitor.azure.com/scripts/c/ms.analytics-web-3.0.2.min.js',
// Integrity hash generated via srihash.org
sourceLibraryCdnIntegrityHash: 'sha384-ZCsysyTvHb4xqC4BgJSay4nwlNIGlT1w5t5YQS5htghoD2XEL2b4SrkhRPhtr9GD'
},
settings: {
account: {
show: true
},
personalization: {
show: true
},
diagnostic: {
show: true
},
language: {
show: true
},
notification: {
show: true
},
extension: {
show: true
},
azure: {
show: true
},
access: {
show: true
},
sharedConnections: {
show: true
},
general: {
show: true
},
connectivity: {
show: true
},
updates: {
show: true
},
extensionUpdates: {
show: true
},
performance: {
show: true
},
advanced: {
show: true
},
proxy: {
show: true
}
}
};
/**
* Environment module class.
*/
export class EnvironmentModule {
static logSourceName = 'ManifestLoader';
/**
* Static mapping for connection information.
*/
static connectionMap = null;
/**
* Static mapping for extensionTargetTypes to a map of extensionTargetIds to entry point ids that fulfill that target
*/
static extensionTargetFulfillmentMap;
/**
* Static mapping for friendly url strings to entrypoint ids
*/
static friendlyUrlMap = null;
/**
* The name of shell.
*/
static nameOfShell = 'msft.sme.shell';
/**
* The default signature if missing manifest.
*/
static defaultSignature = 'version 0.0.0';
/**
* The prefix for identifying an sme-icon reference
*/
static smeIconPrefix = 'sme-icon:';
/**
* All entry points from all modules
*/
static allEntryPoints = null;
/**
* All entry points by type
*/
static entryPointsByType = null;
/**
* All entry points by type
*/
static entryPointsById = null;
/**
* All extension targets from all modules
*/
static allExtensionTargets = null;
/**
* All extension targets by type
*/
static extensionTargetsByType = null;
/**
* All extension targets by type
*/
static extensionTargetsById = null;
/**
* All extension targets by type
*/
static extensionOrigins = null;
/**
* schema file information.
*/
$schema;
/**
* name of module.
*/
name;
/**
* display name of module.
*/
displayName;
/**
* description of set of tools.
*/
description;
/**
* keywords of the module.
*/
keywords;
/**
* origin absolute url.
*/
origin;
/**
* target url to open the iframe.
*/
target;
/**
* signature.
*/
signature;
/**
* The version of this module
*/
version;
/**
* icon url, absolute or relative to Shell url.
*/
icon;
/**
* The support JEA endpoint with PowerShell module.
*/
jea;
/**
* extension targets for this extension
* Defines things that can be extended in this module.
*/
extensionTargets;
/**
* entry points to launch the tool.
*/
entryPoints;
/**
* Assets shared by the module
*/
assets;
/**
* localized resources of strings.
*/
resources;
/**
* Schemas provided for use in this manifest
*/
schemas;
/**
* list of all other available modules for shell.
*/
modules;
/**
* Indicates that this module is being sideLoaded
*/
isSideLoaded;
/**
* The Environment configuration
*/
configuration;
/**
* returns true if the provided origin is a known extension origin
*/
static isExtensionOrigin(origin) {
return this.extensionOrigins.has(origin);
}
/**
* Indicates if a given icon reference is an sme-icon or some other form
* @param iconRef the reference to check
*/
static isSmeIconRef(iconRef) {
return (!MsftSme.isNullOrUndefined(iconRef) && iconRef.startsWith(EnvironmentModule.smeIconPrefix));
}
/**
* Gets the icon class from an iconRef or returns null if the iconRef is not an sme-icon reference
* @param iconRef the reference to check
*/
static getSmeIconClassFromRef(iconRef) {
return (!MsftSme.isNullOrUndefined(iconRef) && EnvironmentModule.isSmeIconRef(iconRef))
? iconRef.substring(EnvironmentModule.smeIconPrefix.length) : null;
}
/**
* Gets the icon url from an iconRef or returns null if the iconRef is an sme-icon reference
* @param iconRef the reference to check
*/
static getFormattedIconRefUrl(iconRef) {
return (MsftSme.isNullOrUndefined(iconRef) || EnvironmentModule.isSmeIconRef(iconRef)) ? null : `url(${iconRef})`;
}
/**
* Processes an icon reference to resolve it to either a sme-icon or absolute url
* @param iconRef The icon reference
* @param module the module that the icon belongs to
*/
static processIconReference(iconRef, module) {
// leave icon ref alone if it is an sme-icon, absolute uri, or null/whitespace
if (MsftSme.isNullOrWhiteSpace(iconRef) || EnvironmentModule.isSmeIconRef(iconRef) || MsftSme.isUriAbsolute(iconRef)) {
return iconRef;
}
return this.toAbsolutePath(module, iconRef);
}
/**
* Converts relative module paths into absolute uris
*/
static toAbsolutePath(module, relativePath) {
const pathComponents = [relativePath];
if (module.target && !module.isSideLoaded) {
pathComponents.unshift(module.target);
}
pathComponents.unshift(module.origin);
return MsftSme.pathJoin('/', pathComponents);
}
/**
* Find resource string for the key.
*
* @param resources The resource.
* @param locale The locale.
* @param key The key string.
*/
static findResource(resources, locale, key) {
const prefix = 'resources:strings:';
if (!key.startsWith(prefix)) {
return key;
}
key = key.substring(prefix.length);
const en = resources.first((value) => value.locale === 'default');
const current = resources.first((value) => value.locale === locale);
if (current && current.strings[key]) {
return current.strings[key];
}
else if (en && en.strings[key]) {
return en.strings[key];
}
return key;
}
/**
* Recursively processes manifest resources
*
* @param module the manifest object.
* @param locale the locale string such as 'en'.
* @param obj current object, defaults to the module itself
*/
static processModuleResources(module, locale, obj = module) {
if (!Array.isArray(module.resources)) {
module.resources = [];
}
const keys = Object.keys(obj);
keys.forEach(key => {
if (typeof obj[key] === 'string') {
// first check the string for localized values
obj[key] = EnvironmentModule.findResource(module.resources, locale, obj[key]);
// if the key is 'icon' treat this field as an icon
if (key === 'icon') {
obj[key] = EnvironmentModule.processIconReference(obj[key], module);
}
}
else if (typeof obj[key] === 'object') {
EnvironmentModule.processModuleResources(module, locale, obj[key]);
}
});
}
static getModuleAssetUri(moduleName, resourceName, version) {
const assets = MsftSme.self().Resources.moduleAssets;
if (assets[moduleName] && assets[moduleName][resourceName] && assets[moduleName][resourceName][version]) {
return assets[moduleName][resourceName][version];
}
return null;
}
/**
* Create environment object from the manifest.
*
* @param manifest the manifest object.
* @param locale the locale string such as 'en'.
*/
static createEnvironment(manifest, locale) {
// use local origin automatically.
manifest.origin = MsftSme.getSafeOrigin();
// initialize tracking of known trusted origins
this.extensionOrigins = new Set();
this.extensionOrigins.add(manifest.origin);
// use current time if version is missing so this enforce browser caching if v= option is used.
manifest.version = manifest.version ? manifest.version : Date.now().toString();
// merge manifest configuration with default configuration
manifest.configuration = MsftSme.deepAssign({}, defaultEnvironmentConfiguration, manifest.configuration);
const modules = manifest.modules || [];
// process manifest entry points separately from children modules
if (manifest.name === 'msft.sme.shell') {
const shellExtensionManifest = { ...manifest };
delete shellExtensionManifest.modules;
shellExtensionManifest.name = 'msft.sme.shell-extensions';
shellExtensionManifest.target = '/extensions';
modules.push(shellExtensionManifest);
}
// Initialize Module Assets
MsftSme.self().Resources.moduleAssets = {};
// process Modules
if (modules && modules.length > 0) {
// first process resources, signature, and origin
for (const module of modules) {
// TODO: signature is going to be removed from modules, for now always use default.
module.signature = EnvironmentModule.defaultSignature;
// if the module has no origin, use the global one.
module.origin = module.origin || manifest.origin;
this.extensionOrigins.add(module.origin);
// process module parts
EnvironmentModule.processModuleResources(module, locale);
delete module['resources'];
// add assets to module assets using absolute paths
if (module.assets) {
const moduleAssets = {};
const assetKeys = Object.keys(module.assets);
assetKeys.forEach(key => {
moduleAssets[key] = {};
const versionKeys = Object.keys(module.assets[key]);
versionKeys.forEach(version => {
moduleAssets[key][version] = this.toAbsolutePath(module, module.assets[key][version]);
});
});
MsftSme.self().Resources.moduleAssets[module.name] = moduleAssets;
}
}
// now process extension targets
for (const module of modules) {
EnvironmentModule.processExtensionTargets(module);
}
// finally process entry points
for (const module of modules) {
EnvironmentModule.processEntryPoints(module);
}
// default entry point collections to be sorted alphabetically
const alphaSort = (a, b) => a.displayName ? a.displayName.localeCompareIgnoreCase(b.displayName) : -1;
if (this.allEntryPoints) {
this.allEntryPoints.sort(alphaSort);
}
else {
this.allEntryPoints = [];
}
if (this.entryPointsByType) {
this.entryPointsByType[EnvironmentModuleEntryPointType.Solution].sort(alphaSort);
this.entryPointsByType[EnvironmentModuleEntryPointType.Tool].sort(alphaSort);
}
// TODO: do we want settings alphabetized?
}
return manifest;
}
/**
* Gets the environment module.
*
* @param name the name of module.
* @return EnvironmentModule the environment module.
*/
static checkEnvironmentInitialized() {
if (!MsftSme || !MsftSme.self().Environment) {
const message = MsftSme.getStrings().MsftSmeShell.Core.Error.EnvironmentNotInitialized.message;
throw Error(message);
}
}
/**
* Gets the environment module.
*
* @param name the name of module.
* @return EnvironmentModule the environment module.
*/
static getEnvironmentModule(name) {
const shellEnvironment = MsftSme.self().Environment;
const modules = shellEnvironment && shellEnvironment.modules;
if (modules) {
for (const module of modules) {
if (module.name === name) {
return module;
}
}
}
if (shellEnvironment.name === name) {
return shellEnvironment;
}
return null;
}
/**
* Process extension targets for quick and easy access later
* @param module the modules to process
*/
static processExtensionTargets(module) {
// initialize tracking structures if they have not been
if (!EnvironmentModule.allExtensionTargets) {
EnvironmentModule.allExtensionTargets = [];
EnvironmentModule.extensionTargetsByType = {};
EnvironmentModule.extensionTargetsById = {};
EnvironmentModule.extensionTargetFulfillmentMap = {};
Object.keys(ExtensionTargetType).forEach(key => this.extensionTargetsByType[ExtensionTargetType[key]] = []);
}
// stop if there are no extension targets in this module
if (!module.extensionTargets) {
return;
}
module.extensionTargets.forEach(extensionTarget => {
// ignore invalid types in the manifest
if (!EnvironmentModule.extensionTargetsByType[extensionTarget.extensionTargetType]) {
Logging.log({
source: EnvironmentModule.logSourceName,
level: LogLevel.Warning,
consoleGroupHeader: `Unable to determine extensionTargetType.`,
message: `Entry point "${extensionTarget.name}" in module "${module.displayName} has a extensionTargetType of: ${extensionTarget.extensionTargetType}`
});
return;
}
// save the module information into the extension target
extensionTarget.parentModule = module;
const extensionTargetId = EnvironmentModule.createFormattedExtensionTarget(extensionTarget);
// save the module information into the extension target
extensionTarget.parentModule = module;
// push to data structures
EnvironmentModule.allExtensionTargets.push(extensionTarget);
EnvironmentModule.extensionTargetsByType[extensionTarget.extensionTargetType].push(extensionTarget);
EnvironmentModule.extensionTargetsById[extensionTargetId] = extensionTarget;
// initialize fulfillment map
EnvironmentModule.extensionTargetFulfillmentMap[extensionTargetId] = [];
});
}
/**
* Process Entry points for quick and easy access later
* @param module the modules to process
*/
static processEntryPoints(module) {
// initialize tracking structures if they have not been
if (!EnvironmentModule.allEntryPoints) {
EnvironmentModule.allEntryPoints = [];
EnvironmentModule.entryPointsByType = {};
EnvironmentModule.entryPointsById = {};
Object.keys(EnvironmentModuleEntryPointType).forEach(key => this.entryPointsByType[EnvironmentModuleEntryPointType[key]] = []);
this.friendlyUrlMap = {
connectionTypes: { to: {}, from: {} },
solutions: { to: {}, from: {} },
tools: { to: {}, from: {} },
settingsForms: { to: {}, from: {} }
};
}
if (!module.entryPoints) {
return;
}
module.entryPoints.forEach(entryPoint => {
// ignore invalid types in the manifest
if (!EnvironmentModule.entryPointsByType[entryPoint.entryPointType]) {
Logging.log({
source: EnvironmentModule.logSourceName,
level: LogLevel.Warning,
consoleGroupHeader: `Unable to determine entryPointType.`,
message: `Entry point "${entryPoint.displayName}" in module "${module.displayName} has a entryPointType of: ${entryPoint.entryPointType}`
});
return;
}
// if we have experiment keys, dont process the entry point if any key is not enabled
if (entryPoint.experimentKeys && entryPoint.experimentKeys.some(key => !MsftSme.isExperimentEnabledRaw(key))) {
return;
}
// save the module information into the entry point
entryPoint.parentModule = module;
const entryPointId = EnvironmentModule.createFormattedEntrypoint(entryPoint);
// push to data structures
EnvironmentModule.allEntryPoints.push(entryPoint);
EnvironmentModule.entryPointsByType[entryPoint.entryPointType].push(entryPoint);
EnvironmentModule.entryPointsById[entryPointId] = entryPoint;
// process url mappings
if (entryPoint.urlName) {
switch (entryPoint.entryPointType) {
case EnvironmentModuleEntryPointType.Solution:
this.friendlyUrlMap.solutions.to[entryPointId] = entryPoint.urlName;
this.friendlyUrlMap.solutions.from[entryPoint.urlName] = entryPointId;
break;
case EnvironmentModuleEntryPointType.Tool:
this.friendlyUrlMap.tools.to[entryPointId] = entryPoint.urlName;
this.friendlyUrlMap.tools.from[entryPoint.urlName] = entryPointId;
break;
case EnvironmentModuleEntryPointType.SettingsForm:
this.friendlyUrlMap.settingsForms.to[entryPointId] = entryPoint.urlName;
this.friendlyUrlMap.settingsForms.from[entryPoint.urlName] = entryPointId;
break;
case EnvironmentModuleEntryPointType.ConnectionProvider:
if (entryPoint.connectionTypeUrlName) {
this.friendlyUrlMap.connectionTypes.to[entryPoint.connectionType] = entryPoint.connectionTypeUrlName;
this.friendlyUrlMap.connectionTypes.from[entryPoint.connectionTypeUrlName] = entryPoint.connectionType;
}
}
}
if (entryPoint.entryPointType === EnvironmentModuleEntryPointType.ConnectionProvider && entryPoint.connectionTypeUrlName) {
this.friendlyUrlMap.connectionTypes.to[entryPoint.connectionType] = entryPoint.connectionTypeUrlName;
this.friendlyUrlMap.connectionTypes.from[entryPoint.connectionTypeUrlName] = entryPoint.connectionType;
}
// process extension mappings
if (entryPoint.extends) {
entryPoint.extends.forEach(extender => {
const extensionTarget = EnvironmentModule.getExtensionTargets(target => {
return target.parentModule.name === extender.module
&& target.name === extender.target;
}).first();
if (MsftSme.isNullOrUndefined(extensionTarget)) {
// if we get here, either that target is no longer supported or the target extension is not installed.
return;
}
const extensionTargetId = EnvironmentModule.createFormattedExtensionTarget(extensionTarget);
EnvironmentModule.extensionTargetFulfillmentMap[extensionTargetId].push(entryPointId);
});
}
});
}
/**
* Evaluates all of the modules in the environment and returns a flat list of all of their entry points.
* optionally filtered by the 'filter' function
*
* @param filter the filter to apply to the entry points.
* @return a flat list of all module entry points
*/
static getExtensionTargets(filter) {
return filter ? EnvironmentModule.allExtensionTargets.filter(filter) : EnvironmentModule.allExtensionTargets;
}
/**
* Evaluates all of the modules in the environment and returns a flat list of all of their entry points.
* optionally filtered by the 'filter' function
*
* @param filter the filter to apply to the entry points.
* @return a flat list of all module entry points
*/
static getEntryPoints(filter) {
EnvironmentModule.checkEnvironmentInitialized();
return filter ? EnvironmentModule.allEntryPoints.filter(filter) : EnvironmentModule.allEntryPoints;
}
/**
* Gets the available entry points from all of the modules in the environment, filtered by type.
*
* @param name the name of module.
* @return EnvironmentModule the environment module.
*/
static getEntryPointsByType(entryPointTypes) {
EnvironmentModule.checkEnvironmentInitialized();
return entryPointTypes.mapMany(type => EnvironmentModule.entryPointsByType[type]);
}
/**
* Gets the connection type mapping data.
*
* @return the mapping object.
*/
static fulfillExtensionTarget(extensionTargetId) {
EnvironmentModule.checkEnvironmentInitialized();
return EnvironmentModule.extensionTargetFulfillmentMap[extensionTargetId];
}
/**
* Gets the connection type mapping data.
*
* @return the mapping object.
*/
static getConnectionMap() {
if (!EnvironmentModule.connectionMap) {
EnvironmentModule.connectionMap = EnvironmentModule.createConnectionMap();
}
return EnvironmentModule.connectionMap;
}
/**
* Gets a friendly url segment from a connection type
* @param connectionType the connection type to map.
* @return string friendly url for the connection type or the connection type if no friendly name exists.
*/
static getFriendlyUrlSegmentForConnectionType(connectionType, fallbackToUnfriendlySegment = true) {
return EnvironmentModule.friendlyUrlMap.connectionTypes.to[connectionType] || (fallbackToUnfriendlySegment ? connectionType : null);
}
/**
* Gets a connection type from a friendly url segment
* @param urlSegment the url segment to map
* @return string connection type found using the friendly url segment
*/
static getConnectionTypeFromFriendlyUrlSegment(urlSegment) {
return EnvironmentModule.friendlyUrlMap.connectionTypes.from[urlSegment];
}
/**
* Gets a friendly url segment from an entry point id
* @param urlSegment the url segment.
* @param entryPointType the type of entry point to look for.
* @return string friendly url for the entry point id
*/
static getFriendlyUrlSegmentForEntryPoint(entryPoint, entryPointType, fallbackToUnfriendlySegment = true) {
switch (entryPointType) {
case EnvironmentModuleEntryPointType.Solution:
return EnvironmentModule.friendlyUrlMap.solutions.to[entryPoint] || (fallbackToUnfriendlySegment ? entryPoint : null);
case EnvironmentModuleEntryPointType.Tool:
return EnvironmentModule.friendlyUrlMap.tools.to[entryPoint] || (fallbackToUnfriendlySegment ? entryPoint : null);
case EnvironmentModuleEntryPointType.SettingsForm:
return EnvironmentModule.friendlyUrlMap.settingsForms.to[entryPoint] || (fallbackToUnfriendlySegment ? entryPoint : null);
}
return null;
}
/**
* Gets a friendly url segment for an entry point
* @param urlSegment the url segment.
* @param entryPointType the type of entry point to look for.
* @return string friendly url for the entry point
*/
static getEntryPointFromFriendlyUrlSegment(urlSegment, entryPointType) {
switch (entryPointType) {
case EnvironmentModuleEntryPointType.Solution:
return EnvironmentModule.friendlyUrlMap.solutions.from[urlSegment];
case EnvironmentModuleEntryPointType.Tool:
return EnvironmentModule.friendlyUrlMap.tools.from[urlSegment];
case EnvironmentModuleEntryPointType.SettingsForm:
return EnvironmentModule.friendlyUrlMap.settingsForms.from[urlSegment];
}
return null;
}
/**
* Gets the connection type information.
*
* @param typeName the type name.
* @return EnvironmentConnectionTypeInfo the connection type information.
*/
static getConnectionTypeInfo(typeName) {
return EnvironmentModule.getConnectionMap()[typeName];
}
static createConnectionMap() {
const map = {};
const providers = this.getEntryPointsByType([EnvironmentModuleEntryPointType.ConnectionProvider]);
providers.forEach(provider => {
if (!provider.connectionTypeDefaultSolution) {
const message = MsftSme.getStrings().MsftSmeShell.Core.Error.EnvironmentMissingDefault.message;
throw new Error(message);
}
const solutionEntrypoint = EnvironmentModule.splitFormattedEntrypoint(provider.connectionTypeDefaultSolution);
const solution = this.getEntryPointsByType([EnvironmentModuleEntryPointType.Solution])
.first(ep => ep.parentModule.name === solutionEntrypoint.moduleName && ep.name === solutionEntrypoint.entrypointName);
map[provider.connectionType] = { provider, solution };
if (solution && solution.parentModule && solution.parentModule.name) {
map[solution.parentModule.name] = map[provider.connectionType];
}
});
return map;
}
/**
* splits an entrypoint identifier string into its respective module and entrypoint names
* @param format the formatted entrypoint identifier string
*/
static splitFormattedEntrypoint(format) {
const parts = format.split('!');
return { moduleName: parts[0], entrypointName: parts[1] };
}
/**
* creates a formatted entrypoint identifier string from an entrypoint
* @param entryPoint the entrypoint to create the string from
*/
static createFormattedEntrypoint(entryPoint) {
return EnvironmentModule.createEntrypointId(entryPoint.parentModule.name, entryPoint.name);
}
static createEntrypointId(moduleName, entryPointName) {
return `${moduleName}!${entryPointName}`;
}
/**
* Create a formatted iframe ID used to link iframes and their html element
* Replace . with - because . is not permitted in css selectors required for testing
* @param parentModuleName the name of the parent module of the iframe content
* @param entryPointName the name of the entry point loaded by the iframe
*/
static createFormattedIFrameId(parentModuleName, entryPointName) {
const parentModuleId = MsftSme.replaceAll(parentModuleName, '.', '-');
return '{0}-{1}'.format(parentModuleId, entryPointName);
}
/**
* splits an extension target identifier string into its respective module and extension target names
* @param format the formatted extension target identifier string
*/
static splitFormattedExtensionTarget(format) {
const parts = format.split('!');
return { moduleName: parts[0], extensionTargetName: parts[1] };
}
/**
* creates a formatted extension target identifier string from an extension target
* @param entryPoint the extension target to create the string from
*/
static createFormattedExtensionTarget(extensionTarget) {
return `${extensionTarget.parentModule.name}!${extensionTarget.name}`;
}
/**
* resolves an entrypoint from a formatted entrypoint identifier string
* @param formattedEntrypointIdentifier the formatted entrypoint identifier string
*/
static resolveEntrypoint(formattedEntrypointIdentifier) {
if (!formattedEntrypointIdentifier) {
return null;
}
const parts = EnvironmentModule.splitFormattedEntrypoint(formattedEntrypointIdentifier);
if (!parts.moduleName || !parts.entrypointName) {
return null;
}
const entryPoints = this.getEntryPoints(ep => ep.name === parts.entrypointName && ep.parentModule.name === parts.moduleName);
return entryPoints[0] || null;
}
/**
* Gets the name of current shell or module.
*/
static getModuleName() {
const self = MsftSme.self();
return self.Init.moduleName;
}
/**
* Gets the version of current shell or module.
*/
static getModuleVersion() {
const self = MsftSme.self();
if (self.Environment.version) {
return self.Environment.version;
}
for (const module of self.Environment.modules) {
if (module.name === self.Init.moduleName && module.version) {
self.Environment.version = module.version;
return module.version;
}
}
return '0.0.0';
}
/**
* Compare the shell version with specified version.
* - this function must be called after NavigationService Init was called, otherwise it
* cannot get current shell version and return false.
* - Tag format is expected be like "<Major>.<Minor>.<Patch>-<Tag>.<Tag version>".
* ex) 1.2.3-myTagName.123
*
* @param inputVersion the version to compare.
* @return true if shell has newer version running.
*/
static shellGreaterOrEqual(inputVersion) {
if (MsftSme.isNullOrWhiteSpace(inputVersion)) {
// shell doesn't give version.
Logging.logError('EnvironmentModule.shellGreaterOrEqual', 'version is empty.');
return false;
}
const shellVersion = MsftSme.self().Init.shellVersion;
if (MsftSme.isNullOrWhiteSpace(shellVersion)) {
// shell doesn't give version.
Logging.logError('EnvironmentModule.shellGreaterOrEqual', 'shell version is not available.');
return false;
}
const tagSegments = inputVersion.split("-");
let inputCoreVersion = inputVersion;
let inputTag = "";
let inputTagVersion = 0;
if (tagSegments.length === 2) {
inputCoreVersion = tagSegments[0];
const tag = tagSegments[1].split(".");
inputTag = tag[0];
if (tag.length === 2) {
const tagNumber = Number(tag[1]);
inputTagVersion = isNaN(tagNumber) ? 0 : tagNumber;
}
}
const inputSegments = inputCoreVersion.split('.');
if (inputSegments.length !== 3) {
// shell doesn't give right version format.
Logging.logError('EnvironmentModule.shellGreaterOrEqual', 'version format is not right.');
return false;
}
const shellTagSegments = shellVersion.split("-");
let shellCoreVersion = shellVersion;
let shellTag = "";
let shellTagVersion = 0;
if (shellTagSegments.length === 2) {
shellCoreVersion = shellTagSegments[0];
const tag = shellTagSegments[1].split(".");
shellTag = tag[0];
if (tag.length === 2) {
const tagNumber = Number(tag[1]);
shellTagVersion = isNaN(tagNumber) ? 0 : tagNumber;
}
}
const shellSegments = shellCoreVersion.split('.');
if (shellSegments.length !== 3) {
// shell doesn't give right version format.
Logging.logError('EnvironmentModule.shellGreaterOrEqual', 'shell version is corrupted.');
return false;
}
const inputDigits = inputSegments.map(digit => {
const num = Number(digit);
return isNaN(num) ? 0 : num;
});
const shellDigits = shellSegments.map(digit => {
const num = Number(digit);
return isNaN(num) ? 0 : num;
});
if (shellDigits[0] < inputDigits[0]
|| (shellDigits[0] === inputDigits[0] && shellDigits[1] < inputDigits[1])
|| (shellDigits[0] === inputDigits[0] && shellDigits[1] === inputDigits[1] && shellDigits[2] < inputDigits[2])
|| (shellDigits[0] === inputDigits[0] && shellDigits[1] === inputDigits[1] && shellDigits[2] === inputDigits[2]
&& shellTag !== "" && shellTag.localeCompare(inputTag) < 0)
|| (shellDigits[0] === inputDigits[0] && shellDigits[1] === inputDigits[1] && shellDigits[2] === inputDigits[2]
&& shellTag !== "" && shellTag.localeCompare(inputTag) === 0) && shellTagVersion < inputTagVersion) {
return false;
}
return true;
}
/**
* Check if the gateway uses API set of version 2.0.0.
* @returns true if version 2.0.0
*/
static get isGatewayV200() {
return MsftSme.self().Init.gatewayApiVersion === '2.0.0';
}
/**
* check if the gateway runs on Windows platform.
* @returns true if Windows platform.
*/
static get isGatewayWindows() {
return MsftSme.self().Init.gatewayPlatform === 'Windows';
}
/**
* Check if the gateway runs on Linux platform.
* @returns true if Linux platform.
*/
static get isGatewayLinux() {
return MsftSme.self().Init.gatewayPlatform === 'Linux';
}
}
//# sourceMappingURL=environment-modules.js.map