UNPKG

@microsoft/windows-admin-center-sdk

Version:

Microsoft - Windows Admin Center Shell

1 lines 14 kB
{"version":3,"sources":["../../../packages/core/manifest/manifest-loader.ts"],"names":[],"mappings":"AAWA;;;GAGG;AACH,qBAAa,cAAc;IACvB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAoB;IACzD,OAAO,CAAC,MAAM,CAAC,UAAU,CAAgB;IACzC,OAAO,CAAC,MAAM,CAAC,YAAY,CAAmB;IAC9C,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAwB;IAC/C,OAAO,CAAC,MAAM,CAAC,cAAc,CAAkD;IAE/E;;OAEG;IACH,IAAW,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,CAEjC;IAED;;OAEG;WACW,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;IAiC3C;;;;;;OAMG;IACH,OAAO,CAAC,MAAM,CAAC,IAAI;IAyFnB;;;OAGG;IACH,OAAO,CAAC,MAAM,CAAC,oBAAoB;IA2CnC;;;;OAIG;IACH,OAAO,CAAC,MAAM,CAAC,sBAAsB;IAkCrC;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,MAAM;CAsBxB","file":"manifest-loader.d.ts","sourcesContent":["import { forkJoin, Observable, of } from 'rxjs';\r\nimport { catchError, map, mergeMap } from 'rxjs/operators';\r\nimport { ErrorExtended } from '../data/error-extended';\r\nimport { NativeQ } from '../data/native-q';\r\nimport { LogLevel } from '../diagnostics/log-level';\r\nimport { LogRecord } from '../diagnostics/log-record';\r\nimport { Logging } from '../diagnostics/logging';\r\nimport { HostCoreManager, HostCoreTokenMode } from '../host/host-core-manager';\r\nimport { SignedHttpRequestToken } from '../security/sign-on-manager';\r\nimport { EnvironmentModule } from './environment-modules';\r\n\r\n/**\r\n * The Manifest service class.\r\n * (Localized string cannot be used in this class due to initialization phase when the strings are not ready yet.)\r\n */\r\nexport class ManifestLoader {\r\n private static readonly logSourceName = 'ManifestLoader';\r\n private static gatewayUrl = 'gatewayUrl';\r\n private static manifestFile = 'manifest.json';\r\n private static deferred = NativeQ.defer<any>();\r\n private static internalLoaded: Promise<void> = ManifestLoader.deferred.promise;\r\n\r\n /**\r\n * Manifest loading promise.\r\n */\r\n public get loaded(): Promise<void> {\r\n return ManifestLoader.internalLoaded;\r\n }\r\n\r\n /**\r\n * Load the manifest.\r\n */\r\n public static loadManifest(): Promise<void> {\r\n const self = MsftSme.self();\r\n const mode: MsftSme.EnvironmentMode = self.Init ? self.Init.mode : MsftSme.EnvironmentMode.NotUse;\r\n const hostCoreManager = new HostCoreManager();\r\n switch (mode) {\r\n case MsftSme.EnvironmentMode.NotUse:\r\n // Turn OFF iframe feature.\r\n ManifestLoader.deferred.reject('no iFrame');\r\n break;\r\n case MsftSme.EnvironmentMode.LoadEmbedded:\r\n // JSON file posting by module iframe.\r\n const manifest: any = {\r\n name: self.Init.moduleName,\r\n version: self.Init.moduleVersion,\r\n signature: EnvironmentModule.defaultSignature,\r\n shell: {\r\n name: EnvironmentModule.nameOfShell,\r\n origin: self.Init.shellOrigin\r\n }\r\n };\r\n\r\n // Turn ON module self-loading.\r\n ManifestLoader.load(hostCoreManager, manifest);\r\n break;\r\n case MsftSme.EnvironmentMode.Load:\r\n // Turn ON iframe feature by Shell and Module.\r\n ManifestLoader.load(hostCoreManager);\r\n break;\r\n }\r\n\r\n return ManifestLoader.internalLoaded;\r\n }\r\n\r\n /**\r\n * Load the manifest into the MsftSme.Environment.\r\n *\r\n * @param hostCoreManager the hostCoreManager object to load the manifest.\r\n * @param manifest the self loading manifest.\r\n * @return Promise<any> the promise object.\r\n */\r\n private static load(hostCoreManager: HostCoreManager, manifest?: any): Promise<any> {\r\n if (manifest) {\r\n ManifestLoader.update(manifest, null);\r\n return ManifestLoader.internalLoaded;\r\n }\r\n\r\n const gatewayUrlParam = MsftSme.getLocationSearchParameter(ManifestLoader.gatewayUrl);\r\n let manifestUrl = ManifestLoader.manifestFile;\r\n if (gatewayUrlParam && MsftSme.self().Init.isProduction && Object.keys(MsftSme.sideLoad()).length === 0) {\r\n // use the gateway endpoint for manifest source.\r\n manifestUrl = `${gatewayUrlParam.value}/${ManifestLoader.manifestFile}`;\r\n }\r\n\r\n hostCoreManager.httpGet(manifestUrl)\r\n .pipe(\r\n mergeMap(result => ManifestLoader.mergeGatewayManifest(hostCoreManager, result.response)),\r\n mergeMap(\r\n shellManifest => {\r\n const response = shellManifest;\r\n if (response.modules) {\r\n return ManifestLoader.fetchSideloadManifests(hostCoreManager)\r\n .pipe(\r\n map(sideLoads => {\r\n const sideloadShellOrigins: string[] = [];\r\n\r\n sideLoads = sideLoads.filter(s => {\r\n if (MsftSme.isNullOrUndefined(s)) {\r\n return false;\r\n }\r\n\r\n const isShell = s.name === EnvironmentModule.nameOfShell;\r\n if (isShell) {\r\n sideloadShellOrigins.push(s.origin);\r\n }\r\n return !isShell;\r\n });\r\n\r\n if (sideloadShellOrigins.length > 0) {\r\n Logging.log(<LogRecord>{\r\n source: ManifestLoader.logSourceName,\r\n level: LogLevel.Warning,\r\n consoleGroupHeader: `Unable to sideload: \"${sideloadShellOrigins}\".`,\r\n message: `Cannot sideload ${EnvironmentModule.nameOfShell} from ${sideloadShellOrigins}.\r\n Did you mean to run ${EnvironmentModule.nameOfShell} locally?`\r\n });\r\n }\r\n return { manifest: response, sideLoads: sideLoads };\r\n }));\r\n }\r\n\r\n return of({ manifest: response, sideLoads: [] });\r\n })\r\n )\r\n .subscribe({\r\n next: result => {\r\n const manifestResult = <MsftSme.MsftSmeEnvironment>result.manifest;\r\n const modules = manifestResult.modules;\r\n const selfInit = MsftSme.self().Init;\r\n selfInit.shellVersion = manifestResult.version;\r\n selfInit.gatewayApiVersion = manifestResult.gatewayApiVersion;\r\n selfInit.gatewayPlatform = manifestResult.gatewayPlatform;\r\n result.sideLoads.forEach(sideLoad => {\r\n if (sideLoad) {\r\n sideLoad.isSideLoaded = true;\r\n const foundIndex = modules.findIndex((item) => item.name === sideLoad.name);\r\n if (foundIndex >= 0) {\r\n modules.splice(foundIndex, 1, sideLoad);\r\n } else {\r\n modules.push(sideLoad);\r\n }\r\n }\r\n });\r\n\r\n ManifestLoader.update(result.manifest, hostCoreManager.token);\r\n },\r\n error: error => {\r\n // communicate main.ts for error message.\r\n const extendedError = <ErrorExtended<any>>error;\r\n if (hostCoreManager.tokenMode === HostCoreTokenMode.Aad) {\r\n extendedError.extendedSource = ErrorExtended.sources.aadSso;\r\n }\r\n\r\n ManifestLoader.deferred.reject(error);\r\n }\r\n });\r\n\r\n return ManifestLoader.internalLoaded;\r\n }\r\n\r\n /**\r\n * Merges the GatewayUrl manifest with the passed in shell manifest\r\n * Merges modules only at this time with a preference for modules included in the shell\r\n */\r\n private static mergeGatewayManifest(hostCoreManager: HostCoreManager, shellManifest: any): Observable<any> {\r\n // it's production mode and no side-loading omits calling manifest.json again.\r\n if (MsftSme.self().Init.isProduction && Object.keys(MsftSme.sideLoad()).length === 0) {\r\n return of(shellManifest);\r\n }\r\n\r\n const gatewayUrlParam = MsftSme.getLocationSearchParameter(ManifestLoader.gatewayUrl);\r\n if (!gatewayUrlParam) {\r\n return of(shellManifest);\r\n }\r\n\r\n return hostCoreManager.getNoCache(`${gatewayUrlParam.value}/${ManifestLoader.manifestFile}`, false, 'json')\r\n .pipe(\r\n map(result => {\r\n const gatewayManifest = result.response;\r\n if (Array.isArray(gatewayManifest.modules)) {\r\n if (!Array.isArray(shellManifest.modules)) {\r\n shellManifest.modules = gatewayManifest.modules;\r\n } else {\r\n gatewayManifest.modules.forEach(mod => {\r\n mod.origin = gatewayUrlParam.value;\r\n const foundIndex = shellManifest.modules.findIndex((item) => item.name === mod.name);\r\n if (foundIndex === -1) {\r\n shellManifest.modules.push(mod);\r\n }\r\n });\r\n }\r\n }\r\n return shellManifest;\r\n }),\r\n catchError(() => {\r\n // no localization\r\n Logging.log(<LogRecord>{\r\n source: ManifestLoader.logSourceName,\r\n level: LogLevel.Warning,\r\n consoleGroupHeader: `Unable to load gateway manifest: \"${gatewayUrlParam.value}\".`,\r\n message: `Cannot load ${gatewayUrlParam.value}. Please make sure that a manifest.json is available at this location.`\r\n });\r\n return of(shellManifest);\r\n })\r\n );\r\n }\r\n\r\n /**\r\n * retrieves all of the side loaded manifests.\r\n *\r\n * @return Observable<any[]> the manifests.\r\n */\r\n private static fetchSideloadManifests(hostCoreManager: HostCoreManager): Observable<any[]> {\r\n const sideLoadList = MsftSme.sideLoad();\r\n if (Object.keys(sideLoadList).length === 0) {\r\n return of([]);\r\n }\r\n\r\n const sideLoadManifestAwaiters: Observable<any>[] = [];\r\n MsftSme.forEachKey<MsftSme.SideLoad>(sideLoadList, (key, sideLoad) => {\r\n sideLoadManifestAwaiters.push(\r\n // don't send credentials when debugging a side-loading module.\r\n hostCoreManager.getNoCache(`${sideLoad.origin}/${ManifestLoader.manifestFile}`, false, 'json', false)\r\n .pipe(\r\n map(result => {\r\n const manifest = result.response;\r\n manifest.origin = sideLoad.origin;\r\n return manifest;\r\n }),\r\n catchError(() => {\r\n // no localization\r\n Logging.log(<LogRecord>{\r\n source: ManifestLoader.logSourceName,\r\n level: LogLevel.Warning,\r\n consoleGroupHeader: `Unable to sideload: \"${sideLoad.origin}\".`,\r\n message: `Cannot sideload ${sideLoad.origin}. Please make sure that an extension is running at this origin.`\r\n });\r\n return of(null);\r\n })\r\n )\r\n );\r\n });\r\n\r\n return forkJoin(sideLoadManifestAwaiters);\r\n }\r\n\r\n /**\r\n * Update the environment by the manifest.\r\n */\r\n private static update(manifest: any, token: SignedHttpRequestToken): void {\r\n try {\r\n const self = MsftSme.self();\r\n if (token) {\r\n // store the last token if exists.\r\n if (!manifest.configuration) {\r\n manifest.configuration = {};\r\n }\r\n\r\n // passed the signOn objec to GatewayConnection object to configure into the SignOnManager.\r\n manifest.configuration.signOn = { signedHttpRequestToken: token };\r\n }\r\n\r\n self.Environment = EnvironmentModule.createEnvironment(manifest, self.Resources.localeId);\r\n ManifestLoader.deferred.resolve();\r\n } catch (e) {\r\n // no localization\r\n const message = 'Unable to load the manifest: {0}'.format(e);\r\n ManifestLoader.deferred.reject(message);\r\n throw new Error(message);\r\n }\r\n }\r\n}\r\n"]}