{"version":3,"sources":["../../../packages/core/data/net.ts"],"names":[],"mappings":"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","file":"net.d.ts","sourcesContent":["import { Observable, of } from 'rxjs';\r\nimport { AjaxError } from 'rxjs/ajax';\r\nimport { catchError, map } from 'rxjs/operators';\r\nimport { Strings } from '../generated/strings';\r\nimport { Crypto } from './crypto';\r\nimport { ErrorExtended } from './error-extended';\r\nimport { HttpStatusCode } from './http-constants';\r\n\r\n/**\r\n * Escape binary string code\r\n * @param data A value representing original binary string code\r\n */\r\ndeclare function escape(data: string): string;\r\n\r\n/**\r\n * Unescape non-binary string code\r\n * @param data A value representing original non-binary string code\r\n */\r\ndeclare function unescape(data: string): string;\r\n\r\n/**\r\n * The options interface of getErrorMessage function\r\n */\r\nexport interface ErrorMessageOptions {\r\n    /**\r\n     * adding additional error message\r\n     * addNativeError: native error code\r\n     */\r\n    addNativeError?: boolean;\r\n\r\n    /**\r\n     * Add error prefix for output string.\r\n     *\r\n     * \"Error: {error message}\"\r\n     */\r\n    errorPrefix?: boolean;\r\n\r\n    /**\r\n     * Use the detailRecordremoteExceptionMessage on the error instead of detailRecord.message\r\n     */\r\n    useRemoteExceptionMessage?: boolean;\r\n}\r\n\r\ninterface Credentials {\r\n    username: string;\r\n    password: string;\r\n    passwordEncryptedWith: string;\r\n    domain: string;\r\n}\r\n\r\n/**\r\n * Net communication class.\r\n * @dynamic\r\n */\r\nexport class Net {\r\n    private static cachedErrorCodeMap: { [index: number]: string };\r\n    private static get errorCodeMap(): { [index: number]: string } {\r\n        if (!Net.cachedErrorCodeMap) {\r\n            const strings = MsftSme.getStrings<Strings>().MsftSmeShell.Core;\r\n            Net.cachedErrorCodeMap = {\r\n                // added from https://msdn.microsoft.com/en-us/library/aa392154(v=vs.85).aspx\r\n                0: strings.ErrorCode.Code0.message,\r\n                5: strings.ErrorCode.Code5.message,\r\n                50: strings.ErrorCode.Code50.message,\r\n                87: strings.ErrorCode.Code87.message,\r\n                110: strings.ErrorCode.Code110.message,\r\n                1323: strings.ErrorCode.Code1323.message,\r\n                1326: strings.ErrorCode.Code1326.message,\r\n                1355: strings.ErrorCode.Code1355.message,\r\n                2224: strings.ErrorCode.Code2224.message,\r\n                2691: strings.ErrorCode.Code2691.message,\r\n                2692: strings.ErrorCode.Code2692.message,\r\n                0x80041087: strings.ErrorCode.Code8004108.message\r\n            };\r\n        }\r\n\r\n        return Net.cachedErrorCodeMap;\r\n    }\r\n\r\n    /**\r\n     * The static definition of Web API URLs.\r\n     */\r\n    public static apiVersionParam = 'api-version';\r\n    public static apiVersion20190201 = '2019-02-01';\r\n    public static apiRoot = '/api/{0}';\r\n    public static batch = '/batch';\r\n    public static streamSocket = '{0}/api/streams/socket/{1}';\r\n    public static downlevel = 'features/downlevelSupport';\r\n    public static downlevelInstall = Net.downlevel + '/install';\r\n    public static downlevelComponents = Net.downlevel + '/components';\r\n    public static extensionsSettings = '/settings/extension';\r\n    public static installedExtensions = '/settings/extension/installed';\r\n    public static extensions = '/extensions';\r\n    public static updatesSettings = '/settings/updates';\r\n    public static isExtensionUpdateAvailable = Net.extensions + '/isUpdateAvailable';\r\n    public static cimClass = 'features/cim/namespaces/{0}/classes/{1}';\r\n    public static cimQuery = 'features/cim/query';\r\n    public static cimInvoke = '/methods/{0}/invoke';\r\n    public static powerShellApiInvokeCommand = 'features/powershellApi/invokeCommand';\r\n    public static powerShellApiSessions = 'features/powershellApi/pssessions/{0}';\r\n    public static powerShellApiExecuteCommand: string = Net.powerShellApiSessions + '/invokeCommand';\r\n    public static powerShellApiRetrieveOutput: string = Net.powerShellApiSessions + '?$expand=output';\r\n    public static powerShellApiCancelCommand: string = Net.powerShellApiSessions + '/cancel';\r\n    public static powerShellConsoleSessions = 'features/powershellConsole/pssessions/{0}';\r\n    public static powerShellConsoleExecuteCommand: string = Net.powerShellConsoleSessions + '/invokeCommand';\r\n    public static powerShellConsoleRetrieveOutput: string = Net.powerShellConsoleSessions + '?$expand=output';\r\n    public static stopCommand: string = Net.powerShellConsoleSessions + '/cancel';\r\n    public static tabCommand: string = Net.powerShellConsoleSessions + '/tab';\r\n    public static userProfile = '/settings/user';\r\n    public static applicationSettings = '/settings/all';\r\n    public static adminSettings = '/settings/admin';\r\n    public static user = '/user';\r\n\r\n    public static fileTransferFormat = 'features/fileTransfer/files/{0}';\r\n    public static fileTransferDownloadPost: string = Net.fileTransferFormat + '/download';\r\n    public static fileTransferUpload: string = Net.fileTransferFormat + '/uploadlink';\r\n\r\n    public static jeaFeature = 'features/jea/endpoint';\r\n    public static jeaExport = Net.jeaFeature + '/export';\r\n\r\n    public static gateway = '/gateway';\r\n    public static gatewayAccessCheck = Net.gateway + '/access/check';\r\n    public static gatewayStatus = Net.gateway + '/status';\r\n\r\n    // {HttpMethod} {relativeNodeUrl}  HTTP/1.1\r\n    public static multiPartCallBodyUrl = '{0} {1} HTTP/1.1';\r\n\r\n    /**\r\n     * Gateway version 2.0.0 Node API set.\r\n     */\r\n    /**\r\n     * WinREST service on Windows platform.\r\n     */\r\n    public static serviceWinRest = 'WinREST';\r\n\r\n    /**\r\n     * WinStream service on Windows platform.\r\n     */\r\n    public static serviceWinStream = 'WinStream';\r\n\r\n    /**\r\n     * LinuxBase on Linux platform.\r\n     */\r\n    public static serviceLinuxBase = 'LinuxBase';\r\n\r\n    /**\r\n     * ActiveDirectory on WinREST.\r\n     */\r\n    public static controllerActiveDirectory = 'ActiveDirectory';\r\n\r\n    /**\r\n     * CIM on WinREST.\r\n     */\r\n    public static controllerCim = 'CIM';\r\n\r\n    /**\r\n     * Extensions on WinREST.\r\n    */\r\n    public static controllerExtensions = 'Extensions';\r\n\r\n    /**\r\n     * FileTransfer on WinREST.\r\n     */\r\n    public static controllerFileTransfer = 'FileTransfer';\r\n\r\n    /**\r\n     * JEA on WinREST.\r\n    */\r\n    public static controllerJea = 'JEA';\r\n\r\n    /**\r\n     * Nuget on WinREST.\r\n     */\r\n    public static controllerNuget = 'Nuget';\r\n\r\n    /**\r\n     * PerformanceCounter on WinREST.\r\n     */\r\n    public static controllerPerformanceCounter = 'PerformanceCounter';\r\n\r\n    /**\r\n     * PowerShell on WinREST.\r\n     */\r\n    public static controllerPowerShell = 'PowerShell';\r\n\r\n    /**\r\n     * PseudoConsole on WinStream.\r\n     */\r\n    public static controllerPseudoConsole = 'PseudoConsole';\r\n\r\n    /**\r\n     * Ssh on LinuxBase.\r\n     */\r\n    public static controllerSsh = 'Ssh';\r\n\r\n    /**\r\n     * SshFile on LinuxBase.\r\n     */\r\n    public static controllerSshFile = 'SshFile';\r\n\r\n    /**\r\n     * State on WinREST.\r\n     */\r\n    public static controllerState = 'State';\r\n\r\n    /**\r\n     * Stream on WinStream.\r\n     */\r\n    public static controllerStream = 'Stream';\r\n\r\n    /**\r\n     * Stream on LinuxBase.\r\n     */\r\n    public static controllerStreamSsh = 'StreamSsh';\r\n\r\n    /**\r\n     * Tcp on WinStream and LinuxBase.\r\n     */\r\n    public static controllerTcp = 'Tcp';\r\n\r\n    /**\r\n     * Wdac on WinREST.\r\n     */\r\n    public static controllerWdac = 'Wdac';\r\n\r\n    /**\r\n     * Socket URL on WinStream.\r\n     */\r\n    public static streamSocketV200 = '{0}/api/services/' + Net.serviceWinStream + '/' + Net.controllerStream + '/socket/{1}';\r\n\r\n    /**\r\n     * Socket URL on LinuxBase.\r\n    */\r\n    public static sshStreamSocket = '{0}/api/services/' + Net.serviceLinuxBase + '/' + Net.controllerStreamSsh + '/socket';\r\n\r\n    /**\r\n     * Encodes the specified data as Base64-encoded URL.\r\n     *\r\n     * If the resultant URL is longer than 260 characters, it is converted to a\r\n     * relative path where each segment (e.g. '/') defines the character length boundary.\r\n     * The HTTP.SYS subsystem in Windows does now allow a URL segment larger than 260\r\n     * characters without changing a Registry key and restarting the OS.\r\n     * @param data The data to be encoded.\r\n     * @return An encoded Base64 URL, potentially segmented by '/' every 260 characters.\r\n     */\r\n    public static toSegmentedBase64Url(data: string): string {\r\n        const MAX_HTTP_SYS_URL_SEGMENT_LENGTH = 260;\r\n        const base64Url = Net.utf8Base64UrlEncode(data);\r\n        const parts = Net.splitByLength(base64Url, MAX_HTTP_SYS_URL_SEGMENT_LENGTH);\r\n        return parts.join('/');\r\n    }\r\n\r\n    /**\r\n     * Update URL with api-version=20190201.\r\n     * @param url the original URL\r\n     * @returns new url string added version parameter.\r\n     */\r\n    public static updateApiVersion20190201(url: string): string {\r\n        const index = url.indexOf('?');\r\n        const prefix = index > 0 ? '&' : '?';\r\n        if (index > 0 && url.indexOf(`${Net.apiVersionParam}=`) > 0) {\r\n            return url;\r\n        }\r\n\r\n        return `${url}${prefix}${Net.apiVersionParam}=${Net.apiVersion20190201}`;\r\n    }\r\n\r\n    /**\r\n     * Convert IPV6 address to literal format.\r\n     *\r\n     * @param ipv6Address the ipv6 address format.\r\n     */\r\n    public static convertIPv6ToLiteral(ipv6Address: string): string {\r\n        let data = '';\r\n        for (let i = 0; i < ipv6Address.length; i++) {\r\n            let ch = ipv6Address.charAt(i);\r\n            if (ch === ':') {\r\n                ch = '-';\r\n            } else if (ch === '%') {\r\n                ch = 's';\r\n            }\r\n\r\n            data += ch;\r\n        }\r\n\r\n        return `${data}.ipv6-literal.net`;\r\n    }\r\n\r\n    /**\r\n     * Convert IPV6 address to literal format.\r\n     *\r\n     * @param ipv6Address the ipv6 address format.\r\n     */\r\n    public static convertLiteralToIPv6(literal: string): string {\r\n        const firstSegment = literal.split('.ipv6-literal.net')[0];\r\n        if (!firstSegment) {\r\n            throw new Error('Not recognized as an IPv6 literal format: \\'{0}\\'!'.format(literal || 'null'));\r\n        }\r\n\r\n        let data = '';\r\n        for (let i = 0; i < firstSegment.length; i++) {\r\n            let ch = firstSegment.charAt(i);\r\n            if (ch === '-') {\r\n                ch = ':';\r\n            } else if (ch === 's') {\r\n                ch = '%';\r\n            }\r\n\r\n            data += ch;\r\n        }\r\n\r\n        return data;\r\n    }\r\n\r\n    /**\r\n     * Encode a string with base64url.\r\n     *\r\n     * @param data the input string.\r\n     * @return string the encoded string.\r\n     */\r\n    public static base64urlEncode(data: string): string {\r\n        // REF: https://tools.ietf.org/html/rfc4648#section-5\r\n        const base64 = window.btoa(data);\r\n        let base64Url = '';\r\n\r\n        for (let i = 0; i < base64.length; i++) {\r\n            const ch = base64.charAt(i);\r\n\r\n            switch (ch) {\r\n                case '+':\r\n                    base64Url += '-';\r\n                    break;\r\n                case '/':\r\n                    base64Url += '_';\r\n                    break;\r\n                case '=':\r\n                    return base64Url;\r\n                default:\r\n                    base64Url += ch;\r\n                    break;\r\n            }\r\n        }\r\n\r\n        return base64Url;\r\n    }\r\n\r\n    /**\r\n     * Decode a base64 url string.\r\n     *\r\n     * @param data the string to decode.\r\n     * @return string the decoded string.\r\n     */\r\n    public static base64urlDecode(data: string): string {\r\n        while (data.length % 4 !== 0) {\r\n            data += '=';\r\n        }\r\n\r\n        data = data.replaceAll('-', '+').replaceAll('_', '/');\r\n        return window.atob(data);\r\n    }\r\n\r\n    /**\r\n     * Encode utf8 string.\r\n     *\r\n     * @param data the unencoded string.\r\n     */\r\n    public static utf8Encode(data: string): string {\r\n        return unescape(encodeURIComponent(data));\r\n    }\r\n\r\n    /**\r\n     * Decode utf8 string.\r\n     *\r\n     * @param data the encoded UTF8 string.\r\n     */\r\n    public static utf8Decode(data: string): string {\r\n        return decodeURIComponent(escape(data));\r\n    }\r\n\r\n    /**\r\n     * Encode with utf8 (first) and base64url (second).\r\n     *\r\n     * @param data data the original string to encode. The string can be full unicode character string.\r\n     * @return string the encoded string used on a part of URL.\r\n     */\r\n    public static utf8Base64UrlEncode(data: string): string {\r\n        const utf8: string = Net.utf8Encode(data);\r\n        return Net.base64urlEncode(utf8);\r\n    }\r\n\r\n    /**\r\n     * Decode with utf8 (second) and base64url (first).\r\n     *\r\n     * @param data data the encoded URL string to decode.\r\n     * @return string the decoded unicode string.\r\n     */\r\n    public static utf8Base64UrlDecode(data: string): string {\r\n        const utf8: string = Net.base64urlDecode(data);\r\n        return Net.utf8Decode(utf8);\r\n    }\r\n\r\n    /**\r\n     * Create a key name from key value pairs.\r\n     *\r\n     * @param properties the key value pairs.\r\n     * @return string the key name.\r\n     */\r\n    public static cimCreateName(properties: any): string {\r\n        const data: string = JSON.stringify(properties);\r\n        const utf8: string = Net.utf8Encode(data);\r\n        return Net.base64urlEncode(utf8);\r\n    }\r\n\r\n    /**\r\n     * Get properties of the item from the response.\r\n     *\r\n     * @param data the item in the response object.\r\n     * @return any the properties.\r\n     */\r\n    public static getItemProperties(data: any): any {\r\n        if (data && data.properties) {\r\n            return data.properties;\r\n        }\r\n\r\n        return data;\r\n    }\r\n\r\n    /**\r\n     * Get properties of first item from the response.\r\n     *\r\n     * @param data the response object.\r\n     * @return any the properties.\r\n     */\r\n    public static getFirstProperties(data: any): any {\r\n        if (data && data.value && data.value.length) {\r\n            if (data.value[0].properties) {\r\n                return data.value[0].properties;\r\n            }\r\n        } else if (data && data.length) {\r\n            return data[0];\r\n        }\r\n\r\n        return Net.getItemProperties(data);\r\n    }\r\n\r\n    /**\r\n     * Get array of items from the response.\r\n     *\r\n     * @param data the response object.\r\n     * @return any the item array.\r\n     */\r\n    public static getItemArray(data: any): any {\r\n        if (data && data.value) {\r\n            return data.value;\r\n        }\r\n\r\n        return data;\r\n    }\r\n\r\n    /**\r\n     * Create JSON string with properties.\r\n     *\r\n     * @param data the input data.\r\n     * @return string the JSON string with properties.\r\n     */\r\n    public static createPropertiesJSONString(data: any): string {\r\n        return JSON.stringify({\r\n            properties: data\r\n        });\r\n    }\r\n\r\n    /**\r\n     * Creates an encoded authentication header.\r\n     *\r\n     * @param usersName name of user.\r\n     * @param password the password.\r\n     * @return the token string.\r\n     */\r\n    public static createEncodedAuthenticationHeader(userNames: string[], password: string, passwordEncryptedWith: string = null): string {\r\n        const credentials: any = {\r\n            ...Net.toUsernameAndDomain(userNames),\r\n            password: password\r\n        };\r\n        if (!MsftSme.isNullOrWhiteSpace(passwordEncryptedWith)) {\r\n            credentials.passwordEncryptedWith = passwordEncryptedWith;\r\n        }\r\n        return window.btoa(Net.utf8Encode(JSON.stringify(credentials)));\r\n    }\r\n\r\n    public static toUsernameAndDomain(value: string): { domain: string, username: string };\r\n    public static toUsernameAndDomain(value: string[]): { domain: string, username: string };\r\n    public static toUsernameAndDomain(value: string | string[]): { domain: string, username: string } {\r\n        let username: string[];\r\n        if (Array.isArray(value)) {\r\n            username = value;\r\n        } else if (value.indexOf('@') >= 0) {\r\n            // domain is empty if UPN is used.\r\n            username = [\"\", value];\r\n        } else {\r\n            username = value.split('\\\\');\r\n        }\r\n\r\n        return {\r\n            // if only a username was provided, use '.' (shorthand for the locale machine hostname)\r\n            domain: username.length === 1 ? '.' : username[0],\r\n            username: username.length === 1 ? username[0] : username[1]\r\n        };\r\n    }\r\n\r\n    /**\r\n     * Creates an encrypted authentication header value.\r\n     *\r\n     * @param jwk the JWK (Json Web Key)\r\n     * @param usersName name of user.\r\n     * @param password the password.\r\n     * @param logonUser the gateway user\r\n     * @param expirationTimeInMs manage as token expiration time in milliseconds\r\n     * @return the token string.\r\n     */\r\n    public static createEncryptedAuthenticationHeader(\r\n        jwk: string,\r\n        userNames: string[],\r\n        password: string,\r\n        logonUser: string,\r\n        expirationTimeInMs: number\r\n    ): Observable<string> {\r\n        const credentials: Credentials = {\r\n            ...Net.toUsernameAndDomain(userNames),\r\n            password: password,\r\n            passwordEncryptedWith: undefined\r\n        };\r\n        const passwordData = Net.createPasswordData(credentials, logonUser, expirationTimeInMs);\r\n        return Crypto.encryptRsaSha1(jwk, passwordData)\r\n            .pipe(\r\n                map(encryptedPassword => {\r\n                    credentials.password = encryptedPassword;\r\n                    credentials.passwordEncryptedWith = 'JWK2';\r\n                    return window.btoa(Net.utf8Encode(JSON.stringify(credentials)));\r\n                }),\r\n                catchError(() => of(\r\n                    window.btoa(Net.utf8Encode(JSON.stringify(credentials)))\r\n                ))\r\n            );\r\n    }\r\n\r\n    private static createPasswordData(\r\n        credentials: Credentials,\r\n        logOnUser: string,\r\n        expirationTimeInMs: number\r\n    ): string {\r\n        const millisecondsInHour = 60 * 60 * 1000;\r\n        const hoursInYear = 365 * 24;\r\n\r\n        const currentTimeStamp = Date.now();\r\n        const expirationOffsetInMilliseconds = expirationTimeInMs || (hoursInYear * millisecondsInHour);\r\n\r\n        const passwordData = {\r\n            p: credentials.password,\r\n            l: logOnUser,\r\n            t: currentTimeStamp,\r\n            e: currentTimeStamp + expirationOffsetInMilliseconds\r\n        };\r\n\r\n        return JSON.stringify(passwordData);\r\n    }\r\n\r\n    /**\r\n     * Creates encrypted data for auth header\r\n     * @param jwk the JSON web key to be used to encrypt data\r\n     * @param data the data to be encrypted\r\n     * @returns an encrypted string\r\n     */\r\n    public static createEncryptedExtensionDataHeader(jwk: string, data: string) {\r\n        return Crypto.encryptRsaSha1(jwk, data)\r\n            .pipe(map(encryptedData => window.btoa(Net.utf8Encode(encryptedData))));\r\n    }\r\n\r\n    /**\r\n     * Create /api/nodes URL with relativeUrl.\r\n     *\r\n     * @param gatewayName The name of gateway.\r\n     * @param nodeName The name of node.\r\n     * @param relativeUrl The relative Url.\r\n     */\r\n    public static gatewayNodeApi(gatewayName: string, nodeName: string, relativeUrl?: string): string {\r\n\r\n        if (!relativeUrl) {\r\n            relativeUrl = '';\r\n        }\r\n\r\n        if (!relativeUrl.startsWith('/')) {\r\n            relativeUrl = '/' + relativeUrl;\r\n        }\r\n\r\n        if (!nodeName) {\r\n            const message = MsftSme.getStrings<Strings>().MsftSmeShell.Core.Error.ArgumentNullError.message;\r\n            throw new Error(message.format('Net/gatewayNodeApi', 'nodeName'));\r\n        }\r\n\r\n        return Net.gatewayApi(gatewayName, `/nodes/${nodeName}${relativeUrl}`);\r\n    }\r\n\r\n    /**\r\n     * Create /api URL with relativeUrl.\r\n     *\r\n     * @param gatewayName The name of gateway.\r\n     * @param nodeName The name of node.\r\n     * @param relativeUrl The relative Url.\r\n     */\r\n    public static gatewayApi(gatewayName: string, relativeUrl?: string): string {\r\n        if (!gatewayName) {\r\n            const message = MsftSme.getStrings<Strings>().MsftSmeShell.Core.Error.ArgumentNullError.message;\r\n            throw new Error(message.format('Net/gatewayApi', 'gatewayName'));\r\n        }\r\n\r\n        if (!relativeUrl) {\r\n            relativeUrl = '';\r\n        }\r\n\r\n        if (!relativeUrl.startsWith('/')) {\r\n            relativeUrl = '/' + relativeUrl;\r\n        }\r\n\r\n        gatewayName = gatewayName.toLowerCase();\r\n        if (!gatewayName.startsWith('http://') && !gatewayName.startsWith('https://')) {\r\n            gatewayName = 'https://' + gatewayName;\r\n        }\r\n\r\n        return `${gatewayName}/api${relativeUrl}`;\r\n    }\r\n\r\n    /**\r\n     * Get error message from ajax result or any other error result and optionally includes native error message.\r\n     *\r\n     * @param error the error context from Net.ajax.\r\n     * @param options add additional optional error message: such as native error messages if possible\r\n     * @return string the error message.\r\n     */\r\n    public static getErrorMessage(error: any, options?: ErrorMessageOptions): string {\r\n        const strings = MsftSme.getStrings<Strings>().MsftSmeShell.Core;\r\n        const prefixFormat = strings.Error.PrefixFormat.message;\r\n        const errorPrefix = options && options.errorPrefix;\r\n        const xhr = error && error.xhr;\r\n        const exception = error && error.exception;\r\n\r\n        if (typeof error === 'string') {\r\n            return errorPrefix ? prefixFormat.format(error) : error;\r\n        }\r\n\r\n        if (xhr && xhr.response) {\r\n            const message = Net.parseErrorResponse(xhr.response, options);\r\n            if (message) {\r\n                return errorPrefix ? prefixFormat.format(message) : message;\r\n            }\r\n        }\r\n\r\n        if (error && error.message) {\r\n            const errorMessage = errorPrefix ? prefixFormat.format(error.message) : error.message;\r\n            if(error.details && Array.isArray(error.details)) {\r\n                // Add details to error message.\r\n                return this.parseErrorDetails(error.details, errorMessage);\r\n            }\r\n            return errorMessage;\r\n        }\r\n\r\n        if (exception && exception.message) {\r\n            return errorPrefix ? prefixFormat.format(exception.message) : exception.message;\r\n        }\r\n\r\n        const statusText = xhr && xhr.statusText;\r\n        if (statusText) {\r\n            return errorPrefix ? prefixFormat.format(statusText) : statusText;\r\n        }\r\n\r\n        throw new Error(strings.Error.NoResponseError.message);\r\n    }\r\n\r\n    private static parseErrorDetails(details: any, message: string): string {\r\n        const strings = MsftSme.getStrings<Strings>().MsftSmeShell.Core;\r\n        const detailsText = strings.Error.Details.text;\r\n            const errorMessages = details.map((detail) => {\r\n              try {\r\n                const parsedDetail = JSON.parse(detail.message);\r\n                if (parsedDetail?.error?.message) {\r\n                  return parsedDetail.error.message;\r\n                }\r\n              } catch (error) {\r\n                // The message is not valid JSON\r\n                return detail.message;\r\n              }\r\n            });\r\n            // Joining the error messages with newline characters\r\n            const detailsMessage = `${detailsText}\\n${errorMessages.join('\\n\\n')}`;\r\n            // Joining the actual error message with details\r\n            return `${message}\\n\\n${detailsMessage}`;\r\n    }\r\n\r\n    /**\r\n     * Get error message from PowerShell ajax response.\r\n     * Can be used by a PowerShell batch consumer to get error message in batch response.\r\n     *\r\n     * @param response the ajax response.\r\n     * @return string the error message.\r\n     */\r\n    public static getPowerShellErrorMessage(response: any): string {\r\n        const message = Net.parseErrorResponse(response);\r\n        if (message) {\r\n            return message;\r\n        }\r\n\r\n        const strings = MsftSme.getStrings<Strings>().MsftSmeShell.Core;\r\n        throw new Error(strings.Error.NoResponseError.message);\r\n    }\r\n\r\n    /**\r\n     * Get error code from ajax result.\r\n     *\r\n     * @param error the error context from Net.ajax.\r\n     * @return string the error code.\r\n     */\r\n    public static getErrorCode(error: any): string {\r\n        const strings = MsftSme.getStrings<Strings>().MsftSmeShell.Core;\r\n        const err = error && error.xhr && error.xhr.response && error.xhr.response.error;\r\n        if (!err) {\r\n            throw new Error(strings.Error.NoResponseError.message);\r\n        }\r\n\r\n        if (err.code) {\r\n            return err.code;\r\n        }\r\n\r\n        throw new Error(strings.Error.NoCode.message);\r\n    }\r\n\r\n    /**\r\n     * Get error message from ajax result excluding error stackTrace\r\n     *\r\n     * @param error the error context from Net.ajax.\r\n     * @return string the error.\r\n     */\r\n    public static getErrorMessageWithoutStacktrace(error: any): string {\r\n        let errorMessage: string = Net.getErrorMessage(error);\r\n        if (errorMessage) {\r\n            const stackTraceIndex: number = errorMessage.toLowerCase().indexOf('stacktrace');\r\n            if (stackTraceIndex > 0) {\r\n                errorMessage = errorMessage.substring(0, stackTraceIndex);\r\n            }\r\n        }\r\n\r\n        return errorMessage;\r\n    }\r\n\r\n    /**\r\n     * Translates error code to string\r\n     *\r\n     * @param code the error code\r\n     * @return string the related error string.\r\n     */\r\n    public static translateErrorCode(code: number): string {\r\n        const strings = MsftSme.getStrings<Strings>().MsftSmeShell.Core;\r\n        const message: string = Net.errorCodeMap[code];\r\n        if (message) {\r\n            return strings.ErrorCode.Translated.message.format(message, code);\r\n        }\r\n\r\n        return strings.ErrorCode.Generic.message.format(code);\r\n    }\r\n\r\n    /**\r\n     * Determine if this is an authorization login error. This code never work if it uses NTLM or Kerberos.\r\n     *\r\n     * @param error The ajax error object.\r\n     */\r\n    public static isUnauthorizedLogin(error: AjaxError): boolean {\r\n        // new login 401 handling.\r\n        const forbidden = error?.xhr?.response?.error?.forbidden;\r\n        return error.status === HttpStatusCode.Unauthorized && forbidden && forbidden === 'UnauthorizedLogin';\r\n    }\r\n\r\n    /**\r\n     * Determine if this is an authorization error.\r\n     *\r\n     * @param error The ajax error object.\r\n     */\r\n    public static isUnauthorized(error: AjaxError): boolean {\r\n        const errorObject = error?.xhr?.response?.error;\r\n        const forbidden = errorObject?.forbidden;\r\n        if (forbidden) {\r\n            // new 403 handling.\r\n            return error.status === HttpStatusCode.Forbidden && forbidden === 'Unauthorized';\r\n        } else {\r\n            // legacy 401 handling. (this should be obsolete now)\r\n            const unauthorized = errorObject?.unauthorized;\r\n            return error.status === HttpStatusCode.Unauthorized && !(unauthorized && unauthorized === 'UnauthorizedLogin');\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Determine if this is an forbidden error.\r\n     *\r\n     * @param error The ajax error object.\r\n     */\r\n    public static isForbidden(error: AjaxError): boolean {\r\n        const forbidden = error?.xhr?.response?.error?.forbidden;\r\n        if (forbidden) {\r\n            // new forbidden.\r\n            return error.status === HttpStatusCode.BadRequest && forbidden === 'Forbidden';\r\n        } else {\r\n            // legacy 403 handling.\r\n            return error.status === HttpStatusCode.Forbidden;\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Get property from an ErrorExtended error object\r\n     *\r\n     * @param error The ErrorExtended error object.\r\n     * @param sourceName The source of the error.\r\n     * @param propertyName The property to get from the error object.\r\n     * @return The value of the property or null if the source doesn't match.\r\n     */\r\n    public static getErrorExtendedProperty<T1, T2>(error: ErrorExtended<T1>, sourceName: string, propertyName: string): T2 {\r\n        if (error.extendedSource &&\r\n            (error.extendedSource === sourceName || error.extendedSource.includes(sourceName))) {\r\n            return <T2>error?.extended[propertyName];\r\n        }\r\n        return null;\r\n    }\r\n\r\n    /**\r\n     * Parse error message from standard ajax error and PowerShell errors.\r\n     *\r\n     * @param response the ajax response.\r\n     * @return string the error message.\r\n     */\r\n    private static parseErrorResponse(response: any, options?: ErrorMessageOptions): string {\r\n        const strings = MsftSme.getStrings<Strings>().MsftSmeShell.Core;\r\n        const err = response && response.error;\r\n        if (err && err.message) {\r\n            const errorMessage = err.message;\r\n\r\n            if (options && options.addNativeError && err.detailRecord) {\r\n                return strings.Error.AddNativeErrorCode.message.format(errorMessage, err.detailRecord.nativeErrorCode);\r\n            }\r\n\r\n            return errorMessage;\r\n        }\r\n\r\n        const psErrors: any[] = response && response.errors;\r\n        if (psErrors && psErrors.length > 0) {\r\n            if (psErrors.length === 1) {\r\n                if (options && options.addNativeError && psErrors[0].detailRecord) {\r\n\r\n                    if (options && options.useRemoteExceptionMessage) {\r\n                        return strings.ErrorFormat.Single.Details.message.format(\r\n                            psErrors[0].errorType,\r\n                            psErrors[0].detailRecord.remoteExceptionMessage,\r\n                            psErrors[0].detailRecord.nativeErrorCode);\r\n                    }\r\n\r\n                    return strings.ErrorFormat.Single.Details.message.format(\r\n                        psErrors[0].errorType,\r\n                        psErrors[0].message,\r\n                        psErrors[0].detailRecord.nativeErrorCode);\r\n                }\r\n\r\n                if (options && options.useRemoteExceptionMessage && psErrors[0].detailRecord) {\r\n                    return strings.ErrorFormat.Single.message.format(\r\n                        psErrors[0].errorType,\r\n                        psErrors[0].detailRecord.remoteExceptionMessage);\r\n                }\r\n                return strings.ErrorFormat.Single.message.format(psErrors[0].errorType, psErrors[0].message);\r\n            }\r\n\r\n            let joinedMessage = '';\r\n            for (let i = 0; i < psErrors.length; i++) {\r\n                if (options && options.addNativeError && psErrors[i].detailRecord) {\r\n                    joinedMessage += strings.ErrorFormat.Multiple.Details.message.format(\r\n                        i + 1,\r\n                        psErrors[i].errorType,\r\n                        psErrors[i].message,\r\n                        psErrors[i].detailRecord.nativeErrorCode);\r\n                } else if (options && options.useRemoteExceptionMessage && psErrors[i].detailRecord) {\r\n                    joinedMessage += strings.ErrorFormat.Multiple.message.format(\r\n                        i + 1,\r\n                        psErrors[i].errorType,\r\n                        psErrors[i].detailRecord.remoteExceptionMessage);\r\n                } else {\r\n                    joinedMessage += strings.ErrorFormat.Multiple.message.format(i + 1, psErrors[i].errorType, psErrors[i].message);\r\n                }\r\n            }\r\n\r\n            return joinedMessage;\r\n        }\r\n\r\n        if (response && response.exception) {\r\n            return response.exception;\r\n        }\r\n\r\n        return null;\r\n    }\r\n\r\n    private static splitByLength(text: string, length: number): string[] {\r\n        const parts = new Array<string>();\r\n\r\n        if (text === null) {\r\n            return parts;\r\n        }\r\n\r\n        const totalLength = text.length;\r\n        const count = Math.ceil(totalLength / length);\r\n\r\n        if (count < 2) {\r\n            parts.push(text);\r\n            return parts;\r\n        }\r\n\r\n        const lastPart = count - 1;\r\n        let position = 0;\r\n\r\n        for (let i = 0; i < lastPart; i++, position += length) {\r\n            parts.push(text.substring(position, position + length));\r\n        }\r\n\r\n        parts.push(text.substring(position));\r\n\r\n        return parts;\r\n    }\r\n}\r\n"]}