UNPKG

@microsoft/windows-admin-center-sdk

Version:

Microsoft - Windows Admin Center Shell

961 lines (959 loc) 38.3 kB
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