From 4208098ab146ad6d37611306c01aac3c93db0941 Mon Sep 17 00:00:00 2001 From: Jeremy Meng Date: Mon, 1 Feb 2021 17:54:34 -0800 Subject: [PATCH] Add Prettier and format code (#415) * Add prettier and configs * npm run format * Fix tslint error - Prettier broke lines but the // tslint:disable-next-line comments remains in the old position. They should be before the applicable lines. - Enforce `SwitchCase` indentation level of 1 to match prettier behavior. --- .prettierignore | 2 + .prettierrc.json | 9 + .scripts/checkConstantsVersion.ts | 26 +- .scripts/checkEverything.ts | 4 +- .scripts/checkForOnlyCalls.ts | 2 +- .scripts/checkPackageJsonVersion.ts | 2 +- .scripts/latest.ts | 2 +- .scripts/local.ts | 2 +- .scripts/testDependentProjects.ts | 26 +- karma.conf.ts | 22 +- lib/credentials/apiKeyCredentials.ts | 10 +- .../azureIdentityTokenCredentialAdapter.ts | 3 +- .../basicAuthenticationCredentials.ts | 6 +- lib/credentials/domainCredentials.ts | 16 +- lib/credentials/tokenCredentials.ts | 5 +- lib/credentials/tokenResponse.ts | 2 +- lib/credentials/topicCredentials.ts | 16 +- lib/fetchHttpClient.ts | 54 +- lib/httpClient.ts | 3 +- lib/httpHeaders.ts | 5 +- lib/httpPipelineLogLevel.ts | 4 +- lib/httpPipelineLogger.ts | 23 +- lib/msRest.ts | 64 +- lib/nodeFetchHttpClient.ts | 18 +- lib/operationArguments.ts | 2 +- lib/operationParameter.ts | 7 +- lib/operationResponse.ts | 2 +- lib/operationSpec.ts | 13 +- lib/policies/agentPolicy.browser.ts | 9 +- lib/policies/agentPolicy.ts | 15 +- lib/policies/deserializationPolicy.ts | 142 ++- lib/policies/exponentialRetryPolicy.ts | 109 +- lib/policies/generateClientRequestIdPolicy.ts | 19 +- lib/policies/logPolicy.ts | 24 +- lib/policies/msRestUserAgentPolicy.browser.ts | 2 +- lib/policies/msRestUserAgentPolicy.ts | 4 +- lib/policies/proxyPolicy.browser.ts | 9 +- lib/policies/proxyPolicy.ts | 18 +- lib/policies/redirectPolicy.ts | 39 +- lib/policies/requestPolicy.ts | 19 +- lib/policies/rpRegistrationPolicy.ts | 107 +- lib/policies/signingPolicy.ts | 24 +- lib/policies/systemErrorRetryPolicy.ts | 103 +- lib/policies/throttlingRetryPolicy.ts | 35 +- lib/policies/userAgentPolicy.ts | 42 +- lib/proxyAgent.ts | 20 +- lib/restError.ts | 11 +- lib/serializer.ts | 402 ++++-- lib/serviceClient.ts | 331 +++-- lib/url.ts | 155 +-- lib/util/base64.ts | 2 +- lib/util/constants.ts | 10 +- lib/util/utils.ts | 69 +- lib/util/xml.browser.ts | 24 +- lib/util/xml.ts | 6 +- lib/webResource.ts | 132 +- lib/xhrHttpClient.ts | 68 +- package.json | 2 + rollup.config.ts | 18 +- samples/node-sample.ts | 5 +- test/credentialTests.ts | 34 +- test/data/TestClient/lib/models/mappers.ts | 382 +++--- test/defaultHttpClientTests.ts | 120 +- test/logFilterTests.ts | 29 +- test/mockHttp.ts | 31 +- test/msAssert.ts | 26 +- test/msRestUserAgentPolicyTests.ts | 18 +- test/operationParameterTests.ts | 28 +- test/policies/agentPolicyTests.ts | 27 +- test/policies/deserializationPolicyTests.ts | 349 ++--- test/policies/proxyPolicyTests.ts | 39 +- test/policies/throttlingRetryPolicyTests.ts | 34 +- test/proxyAgent.node.ts | 42 +- test/serializationTests.ts | 1126 ++++++++++------- test/serviceClientTests.ts | 648 ++++++---- test/urlTests.ts | 230 ++-- test/xhrTests.browser.ts | 26 +- test/xmlTests.ts | 54 +- tslint.json | 8 +- webpack.testconfig.ts | 46 +- 80 files changed, 3610 insertions(+), 2012 deletions(-) create mode 100644 .prettierignore create mode 100644 .prettierrc.json diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..a9e8bc2 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,2 @@ +typings/ +**/*.d.ts diff --git a/.prettierrc.json b/.prettierrc.json new file mode 100644 index 0000000..405804b --- /dev/null +++ b/.prettierrc.json @@ -0,0 +1,9 @@ +{ + "arrowParens": "always", + "bracketSpacing": true, + "endOfLine": "lf", + "printWidth": 100, + "semi": true, + "singleQuote": false, + "tabWidth": 2 +} diff --git a/.scripts/checkConstantsVersion.ts b/.scripts/checkConstantsVersion.ts index 7c32a9e..4867f19 100644 --- a/.scripts/checkConstantsVersion.ts +++ b/.scripts/checkConstantsVersion.ts @@ -1,4 +1,11 @@ -import { findPackageJsonFileSync, PackageJson, readPackageJsonFileSync, getParentFolderPath, joinPath, fileExistsSync } from "@ts-common/azure-js-dev-tools"; +import { + findPackageJsonFileSync, + PackageJson, + readPackageJsonFileSync, + getParentFolderPath, + joinPath, + fileExistsSync, +} from "@ts-common/azure-js-dev-tools"; import { readFileSync } from "fs"; import { Logger, getDefaultLogger } from "@azure/logger-js"; @@ -21,20 +28,29 @@ export function checkConstantsVersion(): number { error(`Could not find a version property in ${packageJsonFilePath}.`); } else { const repositoryRootFolderPath: string = getParentFolderPath(packageJsonFilePath); - const constantsTsFilePath: string = joinPath(repositoryRootFolderPath, "lib/util/constants.ts"); + const constantsTsFilePath: string = joinPath( + repositoryRootFolderPath, + "lib/util/constants.ts" + ); if (!fileExistsSync(constantsTsFilePath)) { error(`${constantsTsFilePath} doesn't exist anymore. Where'd it go?`); } else { - const constantsTsFileContents: string = readFileSync(constantsTsFilePath, { encoding: "utf8" }); + const constantsTsFileContents: string = readFileSync(constantsTsFilePath, { + encoding: "utf8", + }); const regularExpressionString = `msRestVersion: "(.*)"`; const regularExpression = new RegExp(regularExpressionString); const match: RegExpMatchArray | null = constantsTsFileContents.match(regularExpression); if (!match) { error(`${constantsTsFilePath} doesn't contain a match for ${regularExpressionString}.`); } else if (match[1] !== packageVersion) { - error(`Expected ${constantsTsFilePath} to contain an msRestVersion property with the value "${packageVersion}", but it was "${match[1]}" instead.`); + error( + `Expected ${constantsTsFilePath} to contain an msRestVersion property with the value "${packageVersion}", but it was "${match[1]}" instead.` + ); } else { - logger.logInfo(`${constantsTsFilePath} contained the correct value for msRestVersion ("${packageVersion}").`); + logger.logInfo( + `${constantsTsFilePath} contained the correct value for msRestVersion ("${packageVersion}").` + ); } } } diff --git a/.scripts/checkEverything.ts b/.scripts/checkEverything.ts index e727d89..8fb5a87 100644 --- a/.scripts/checkEverything.ts +++ b/.scripts/checkEverything.ts @@ -4,6 +4,6 @@ import { checkConstantsVersion } from "./checkConstantsVersion"; checkEverything({ additionalChecks: { name: "Constants.ts Version", - check: checkConstantsVersion - } + check: checkConstantsVersion, + }, }); diff --git a/.scripts/checkForOnlyCalls.ts b/.scripts/checkForOnlyCalls.ts index c574860..9b0b1a6 100644 --- a/.scripts/checkForOnlyCalls.ts +++ b/.scripts/checkForOnlyCalls.ts @@ -1,3 +1,3 @@ import { checkForOnlyCalls } from "@ts-common/azure-js-dev-tools"; -checkForOnlyCalls(); \ No newline at end of file +checkForOnlyCalls(); diff --git a/.scripts/checkPackageJsonVersion.ts b/.scripts/checkPackageJsonVersion.ts index 845b8a0..2942e7d 100644 --- a/.scripts/checkPackageJsonVersion.ts +++ b/.scripts/checkPackageJsonVersion.ts @@ -1,3 +1,3 @@ import { checkPackageJsonVersion } from "@ts-common/azure-js-dev-tools"; -checkPackageJsonVersion(); \ No newline at end of file +checkPackageJsonVersion(); diff --git a/.scripts/latest.ts b/.scripts/latest.ts index bc71731..a898d50 100644 --- a/.scripts/latest.ts +++ b/.scripts/latest.ts @@ -1,3 +1,3 @@ import { changeClonedDependenciesTo } from "@ts-common/azure-js-dev-tools"; -changeClonedDependenciesTo(__dirname, "latest"); \ No newline at end of file +changeClonedDependenciesTo(__dirname, "latest"); diff --git a/.scripts/local.ts b/.scripts/local.ts index e3d8f5d..b3ac17e 100644 --- a/.scripts/local.ts +++ b/.scripts/local.ts @@ -1,3 +1,3 @@ import { changeClonedDependenciesTo } from "@ts-common/azure-js-dev-tools"; -changeClonedDependenciesTo(__dirname, "local"); \ No newline at end of file +changeClonedDependenciesTo(__dirname, "local"); diff --git a/.scripts/testDependentProjects.ts b/.scripts/testDependentProjects.ts index e88e182..de684bb 100644 --- a/.scripts/testDependentProjects.ts +++ b/.scripts/testDependentProjects.ts @@ -1,5 +1,11 @@ import path from "path"; -import { run, RunResult, RunOptions, Command, commandToString } from "@ts-common/azure-js-dev-tools"; +import { + run, + RunResult, + RunOptions, + Command, + commandToString, +} from "@ts-common/azure-js-dev-tools"; async function execAndLog(executable: string, args?: string[], options?: RunOptions): Promise { const command: Command = { @@ -16,7 +22,11 @@ async function execAndLog(executable: string, args?: string[], options?: RunOpti showResult: true, }); - console.log(`\nResult of "${commandToString(command)}" [Exit code: ${result.exitCode}]:\n` + result.stdout + "\n"); + console.log( + `\nResult of "${commandToString(command)}" [Exit code: ${result.exitCode}]:\n` + + result.stdout + + "\n" + ); if (result.exitCode) { console.error(`Error while running "${commandToString(command)}": ${result.error}`); @@ -29,19 +39,21 @@ async function execAndLog(executable: string, args?: string[], options?: RunOpti async function cloneRepository(projectName: string, projectDirectory: string) { const gitHubUrl = `https://github.com/Azure/${projectName}.git`; await execAndLog(`git`, ["clone", gitHubUrl, projectDirectory, "--recursive"]); - await execAndLog(`npm`, [ "install" ], { executionFolderPath: projectDirectory }); + await execAndLog(`npm`, ["install"], { executionFolderPath: projectDirectory }); } async function buildAndTest(projectDirectory: string) { - await execAndLog(`npm`, [ "run", "build" ], { executionFolderPath: projectDirectory }); - await execAndLog(`npm`, [ "run", "test" ], { executionFolderPath: projectDirectory }); + await execAndLog(`npm`, ["run", "build"], { executionFolderPath: projectDirectory }); + await execAndLog(`npm`, ["run", "test"], { executionFolderPath: projectDirectory }); } async function cloneAndRunTest(msRestJsDirectory: string, projectName: string) { const projectDirectory = path.join(msRestJsDirectory, `../.tmp/${projectName}`); await cloneRepository(projectName, projectDirectory); - await execAndLog(`npm`, [ "install", msRestJsDirectory ], { executionFolderPath: projectDirectory }); + await execAndLog(`npm`, ["install", msRestJsDirectory], { + executionFolderPath: projectDirectory, + }); const additionalCommands: string[] = process.argv.slice(3); for (const command of additionalCommands) { @@ -49,7 +61,7 @@ async function cloneAndRunTest(msRestJsDirectory: string, projectName: string) { } await buildAndTest(projectDirectory); - await execAndLog(`rm`, [ "-rf", projectDirectory ]); + await execAndLog(`rm`, ["-rf", projectDirectory]); } (async () => { diff --git a/karma.conf.ts b/karma.conf.ts index 8c1bbf3..30b0f0f 100644 --- a/karma.conf.ts +++ b/karma.conf.ts @@ -1,14 +1,10 @@ const defaults = { - port: 9876 + port: 9876, }; module.exports = function (config: any) { config.set({ - plugins: [ - "karma-mocha", - "karma-chrome-launcher", - "karma-firefox-launcher" - ], + plugins: ["karma-mocha", "karma-chrome-launcher", "karma-firefox-launcher"], // frameworks to use // available frameworks: https://npmjs.org/browse/keyword/karma-adapter @@ -19,7 +15,7 @@ module.exports = function (config: any) { { pattern: "dist/msRest.browser.js" }, { pattern: "dist/msRest.browser.js.map", included: false }, { pattern: "test/msRest.browser.test.js" }, - { pattern: "test/msRest.browser.test.js.map", included: false } + { pattern: "test/msRest.browser.test.js.map", included: false }, ], // test results reporter to use @@ -52,16 +48,20 @@ module.exports = function (config: any) { customLaunchers: { ChromeNoSecurity: { base: "ChromeHeadless", - flags: ["--disable-web-security"] + flags: ["--disable-web-security"], }, ChromeDebugging: { base: "Chrome", - flags: [`http://localhost:${defaults.port}/debug.html`, "--auto-open-devtools-for-tabs", "--disable-web-security"] + flags: [ + `http://localhost:${defaults.port}/debug.html`, + "--auto-open-devtools-for-tabs", + "--disable-web-security", + ], }, FirefoxDebugging: { base: "Firefox", - flags: ["-url", `http://localhost:${defaults.port}/debug.html`, "-devtools"] - } + flags: ["-url", `http://localhost:${defaults.port}/debug.html`, "-devtools"], + }, }, }); }; diff --git a/lib/credentials/apiKeyCredentials.ts b/lib/credentials/apiKeyCredentials.ts index e433c53..cface5a 100644 --- a/lib/credentials/apiKeyCredentials.ts +++ b/lib/credentials/apiKeyCredentials.ts @@ -39,7 +39,9 @@ export class ApiKeyCredentials implements ServiceClientCredentials { */ constructor(options: ApiKeyCredentialOptions) { if (!options || (options && !options.inHeader && !options.inQuery)) { - throw new Error(`options cannot be null or undefined. Either "inHeader" or "inQuery" property of the options object needs to be provided.`); + throw new Error( + `options cannot be null or undefined. Either "inHeader" or "inQuery" property of the options object needs to be provided.` + ); } this.inHeader = options.inHeader; this.inQuery = options.inQuery; @@ -53,7 +55,9 @@ export class ApiKeyCredentials implements ServiceClientCredentials { */ signRequest(webResource: WebResourceLike): Promise { if (!webResource) { - return Promise.reject(new Error(`webResource cannot be null or undefined and must be of type "object".`)); + return Promise.reject( + new Error(`webResource cannot be null or undefined and must be of type "object".`) + ); } if (this.inHeader) { @@ -82,4 +86,4 @@ export class ApiKeyCredentials implements ServiceClientCredentials { return Promise.resolve(webResource); } -} \ No newline at end of file +} diff --git a/lib/credentials/azureIdentityTokenCredentialAdapter.ts b/lib/credentials/azureIdentityTokenCredentialAdapter.ts index 3dfbb9e..9441769 100644 --- a/lib/credentials/azureIdentityTokenCredentialAdapter.ts +++ b/lib/credentials/azureIdentityTokenCredentialAdapter.ts @@ -14,8 +14,7 @@ const DEFAULT_AUTHORIZATION_SCHEME = "Bearer"; * This class provides a simple extension to use {@link TokenCredential} from `@azure/identity` library to * use with legacy Azure SDKs that accept {@link ServiceClientCredentials} family of credentials for authentication. */ -export class AzureIdentityCredentialAdapter - implements ServiceClientCredentials { +export class AzureIdentityCredentialAdapter implements ServiceClientCredentials { private azureTokenCredential: TokenCredential; private scopes: string | string[]; constructor( diff --git a/lib/credentials/basicAuthenticationCredentials.ts b/lib/credentials/basicAuthenticationCredentials.ts index 3fd2c9d..e92242d 100644 --- a/lib/credentials/basicAuthenticationCredentials.ts +++ b/lib/credentials/basicAuthenticationCredentials.ts @@ -22,7 +22,11 @@ export class BasicAuthenticationCredentials implements ServiceClientCredentials * @param {string} password Password. * @param {string} [authorizationScheme] The authorization scheme. */ - constructor(userName: string, password: string, authorizationScheme: string = DEFAULT_AUTHORIZATION_SCHEME) { + constructor( + userName: string, + password: string, + authorizationScheme: string = DEFAULT_AUTHORIZATION_SCHEME + ) { if (userName === null || userName === undefined || typeof userName.valueOf() !== "string") { throw new Error("userName cannot be null or undefined and must be of type string."); } diff --git a/lib/credentials/domainCredentials.ts b/lib/credentials/domainCredentials.ts index 95a8e78..bf6615b 100644 --- a/lib/credentials/domainCredentials.ts +++ b/lib/credentials/domainCredentials.ts @@ -4,20 +4,20 @@ import { ApiKeyCredentials, ApiKeyCredentialOptions } from "./apiKeyCredentials"; export class DomainCredentials extends ApiKeyCredentials { - /** - * Creates a new EventGrid DomainCredentials object. - * - * @constructor - * @param {string} domainKey The EventGrid domain key - */ + /** + * Creates a new EventGrid DomainCredentials object. + * + * @constructor + * @param {string} domainKey The EventGrid domain key + */ constructor(domainKey: string) { if (!domainKey || (domainKey && typeof domainKey !== "string")) { throw new Error("domainKey cannot be null or undefined and must be of type string."); } const options: ApiKeyCredentialOptions = { inHeader: { - "aeg-sas-key": domainKey - } + "aeg-sas-key": domainKey, + }, }; super(options); } diff --git a/lib/credentials/tokenCredentials.ts b/lib/credentials/tokenCredentials.ts index f7a938e..0151630 100644 --- a/lib/credentials/tokenCredentials.ts +++ b/lib/credentials/tokenCredentials.ts @@ -39,7 +39,10 @@ export class TokenCredentials implements ServiceClientCredentials { */ signRequest(webResource: WebResourceLike) { if (!webResource.headers) webResource.headers = new HttpHeaders(); - webResource.headers.set(HeaderConstants.AUTHORIZATION, `${this.authorizationScheme} ${this.token}`); + webResource.headers.set( + HeaderConstants.AUTHORIZATION, + `${this.authorizationScheme} ${this.token}` + ); return Promise.resolve(webResource); } } diff --git a/lib/credentials/tokenResponse.ts b/lib/credentials/tokenResponse.ts index 1ad9a9f..aef8969 100644 --- a/lib/credentials/tokenResponse.ts +++ b/lib/credentials/tokenResponse.ts @@ -9,4 +9,4 @@ export interface TokenResponse { readonly tokenType: string; readonly accessToken: string; readonly [x: string]: any; -} \ No newline at end of file +} diff --git a/lib/credentials/topicCredentials.ts b/lib/credentials/topicCredentials.ts index 66e22fd..55d435a 100644 --- a/lib/credentials/topicCredentials.ts +++ b/lib/credentials/topicCredentials.ts @@ -4,20 +4,20 @@ import { ApiKeyCredentials, ApiKeyCredentialOptions } from "./apiKeyCredentials"; export class TopicCredentials extends ApiKeyCredentials { - /** - * Creates a new EventGrid TopicCredentials object. - * - * @constructor - * @param {string} topicKey The EventGrid topic key - */ + /** + * Creates a new EventGrid TopicCredentials object. + * + * @constructor + * @param {string} topicKey The EventGrid topic key + */ constructor(topicKey: string) { if (!topicKey || (topicKey && typeof topicKey !== "string")) { throw new Error("topicKey cannot be null or undefined and must be of type string."); } const options: ApiKeyCredentialOptions = { inHeader: { - "aeg-sas-key": topicKey - } + "aeg-sas-key": topicKey, + }, }; super(options); } diff --git a/lib/fetchHttpClient.ts b/lib/fetchHttpClient.ts index ef5ad00..bc35872 100644 --- a/lib/fetchHttpClient.ts +++ b/lib/fetchHttpClient.ts @@ -20,13 +20,20 @@ interface FetchError extends Error { export abstract class FetchHttpClient implements HttpClient { async sendRequest(httpRequest: WebResourceLike): Promise { if (!httpRequest && typeof httpRequest !== "object") { - throw new Error("'httpRequest' (WebResource) cannot be null or undefined and must be of type object."); + throw new Error( + "'httpRequest' (WebResource) cannot be null or undefined and must be of type object." + ); } const abortController = new AbortController(); if (httpRequest.abortSignal) { if (httpRequest.abortSignal.aborted) { - throw new RestError("The request was aborted", RestError.REQUEST_ABORTED_ERROR, undefined, httpRequest); + throw new RestError( + "The request was aborted", + RestError.REQUEST_ABORTED_ERROR, + undefined, + httpRequest + ); } httpRequest.abortSignal.addEventListener("abort", (event: Event) => { @@ -46,7 +53,7 @@ export abstract class FetchHttpClient implements HttpClient { const formData: any = httpRequest.formData; const requestForm = new FormData(); const appendFormValue = (key: string, value: any) => { - // value function probably returns a stream so we can provide a fresh stream on each retry + // value function probably returns a stream so we can provide a fresh stream on each retry if (typeof value === "function") { value = value(); } @@ -72,7 +79,10 @@ export abstract class FetchHttpClient implements HttpClient { const contentType = httpRequest.headers.get("Content-Type"); if (contentType && contentType.indexOf("multipart/form-data") !== -1) { if (typeof requestForm.getBoundary === "function") { - httpRequest.headers.set("Content-Type", `multipart/form-data; boundary=${requestForm.getBoundary()}`); + httpRequest.headers.set( + "Content-Type", + `multipart/form-data; boundary=${requestForm.getBoundary()}` + ); } else { // browser will automatically apply a suitable content-type header httpRequest.headers.remove("Content-Type"); @@ -81,8 +91,10 @@ export abstract class FetchHttpClient implements HttpClient { } let body = httpRequest.body - ? (typeof httpRequest.body === "function" ? httpRequest.body() : httpRequest.body) - : undefined; + ? typeof httpRequest.body === "function" + ? httpRequest.body() + : httpRequest.body + : undefined; if (httpRequest.onUploadProgress && httpRequest.body) { let loadedBytes = 0; const uploadReportStream = new Transform({ @@ -90,7 +102,7 @@ export abstract class FetchHttpClient implements HttpClient { loadedBytes += chunk.length; httpRequest.onUploadProgress!({ loadedBytes }); callback(undefined, chunk); - } + }, }); if (isReadableStream(body)) { @@ -102,14 +114,16 @@ export abstract class FetchHttpClient implements HttpClient { body = uploadReportStream; } - const platformSpecificRequestInit: Partial = await this.prepareRequest(httpRequest); + const platformSpecificRequestInit: Partial = await this.prepareRequest( + httpRequest + ); const requestInit: RequestInit = { body: body, headers: httpRequest.headers.rawHeaders(), method: httpRequest.method, signal: abortController.signal, - ...platformSpecificRequestInit + ...platformSpecificRequestInit, }; try { @@ -120,12 +134,14 @@ export abstract class FetchHttpClient implements HttpClient { headers: headers, request: httpRequest, status: response.status, - readableStreamBody: httpRequest.streamResponseBody ? (response.body as unknown) as NodeJS.ReadableStream : undefined, + readableStreamBody: httpRequest.streamResponseBody + ? ((response.body as unknown) as NodeJS.ReadableStream) + : undefined, bodyAsText: !httpRequest.streamResponseBody ? await response.text() : undefined, }; const onDownloadProgress = httpRequest.onDownloadProgress; - if (onDownloadProgress) { + if (onDownloadProgress) { const responseBody: ReadableStream | undefined = response.body || undefined; if (isReadableStream(responseBody)) { @@ -135,7 +151,7 @@ export abstract class FetchHttpClient implements HttpClient { loadedBytes += chunk.length; onDownloadProgress({ loadedBytes }); callback(undefined, chunk); - } + }, }); responseBody.pipe(downloadReportStream); operationResponse.readableStreamBody = downloadReportStream; @@ -154,9 +170,19 @@ export abstract class FetchHttpClient implements HttpClient { } catch (error) { const fetchError: FetchError = error; if (fetchError.code === "ENOTFOUND") { - throw new RestError(fetchError.message, RestError.REQUEST_SEND_ERROR, undefined, httpRequest); + throw new RestError( + fetchError.message, + RestError.REQUEST_SEND_ERROR, + undefined, + httpRequest + ); } else if (fetchError.type === "aborted") { - throw new RestError("The request was aborted", RestError.REQUEST_ABORTED_ERROR, undefined, httpRequest); + throw new RestError( + "The request was aborted", + RestError.REQUEST_ABORTED_ERROR, + undefined, + httpRequest + ); } throw fetchError; diff --git a/lib/httpClient.ts b/lib/httpClient.ts index 47357ec..0d01984 100644 --- a/lib/httpClient.ts +++ b/lib/httpClient.ts @@ -6,5 +6,4 @@ import { RequestPolicy } from "./policies/requestPolicy"; /** * An interface that can send HttpRequests and receive promised HttpResponses. */ -export interface HttpClient extends RequestPolicy { -} +export interface HttpClient extends RequestPolicy {} diff --git a/lib/httpHeaders.ts b/lib/httpHeaders.ts index 80ce181..698279a 100644 --- a/lib/httpHeaders.ts +++ b/lib/httpHeaders.ts @@ -126,7 +126,10 @@ export class HttpHeaders { * @param headerValue The value of the header to set. */ public set(headerName: string, headerValue: string | number): void { - this._headersMap[getHeaderKey(headerName)] = { name: headerName, value: headerValue.toString() }; + this._headersMap[getHeaderKey(headerName)] = { + name: headerName, + value: headerValue.toString(), + }; } /** diff --git a/lib/httpPipelineLogLevel.ts b/lib/httpPipelineLogLevel.ts index 045be5b..a8cf3a5 100644 --- a/lib/httpPipelineLogLevel.ts +++ b/lib/httpPipelineLogLevel.ts @@ -23,5 +23,5 @@ export enum HttpPipelineLogLevel { /** * An information log. */ - INFO -} \ No newline at end of file + INFO, +} diff --git a/lib/httpPipelineLogger.ts b/lib/httpPipelineLogger.ts index ffec883..47929c4 100644 --- a/lib/httpPipelineLogger.ts +++ b/lib/httpPipelineLogger.ts @@ -29,8 +29,7 @@ export class ConsoleHttpPipelineLogger implements HttpPipelineLogger { * Create a new ConsoleHttpPipelineLogger. * @param minimumLogLevel The log level threshold for what logs will be logged. */ - constructor(public minimumLogLevel: HttpPipelineLogLevel) { - } + constructor(public minimumLogLevel: HttpPipelineLogLevel) {} /** * Log the provided message. @@ -40,17 +39,17 @@ export class ConsoleHttpPipelineLogger implements HttpPipelineLogger { log(logLevel: HttpPipelineLogLevel, message: string): void { const logMessage = `${HttpPipelineLogLevel[logLevel]}: ${message}`; switch (logLevel) { - case HttpPipelineLogLevel.ERROR: - console.error(logMessage); - break; + case HttpPipelineLogLevel.ERROR: + console.error(logMessage); + break; - case HttpPipelineLogLevel.WARNING: - console.warn(logMessage); - break; + case HttpPipelineLogLevel.WARNING: + console.warn(logMessage); + break; - case HttpPipelineLogLevel.INFO: - console.log(logMessage); - break; + case HttpPipelineLogLevel.INFO: + console.log(logMessage); + break; } } -} \ No newline at end of file +} diff --git a/lib/msRest.ts b/lib/msRest.ts index 41c4712..fe674ff 100644 --- a/lib/msRest.ts +++ b/lib/msRest.ts @@ -1,7 +1,17 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. See License.txt in the project root for license information. -export { WebResource, WebResourceLike, HttpRequestBody, RequestPrepareOptions, HttpMethods, ParameterValue, RequestOptionsBase, TransferProgressEvent, AbortSignalLike } from "./webResource"; +export { + WebResource, + WebResourceLike, + HttpRequestBody, + RequestPrepareOptions, + HttpMethods, + ParameterValue, + RequestOptionsBase, + TransferProgressEvent, + AbortSignalLike, +} from "./webResource"; export { DefaultHttpClient } from "./defaultHttpClient"; export { HttpClient } from "./httpClient"; export { HttpHeaders, HttpHeadersLike } from "./httpHeaders"; @@ -10,14 +20,24 @@ export { HttpPipelineLogger } from "./httpPipelineLogger"; export { HttpPipelineLogLevel } from "./httpPipelineLogLevel"; export { RestError } from "./restError"; export { OperationArguments } from "./operationArguments"; -export { OperationParameter, OperationQueryParameter, OperationURLParameter } from "./operationParameter"; +export { + OperationParameter, + OperationQueryParameter, + OperationURLParameter, +} from "./operationParameter"; export { OperationResponse } from "./operationResponse"; export { OperationSpec } from "./operationSpec"; export { ServiceClient, ServiceClientOptions, flattenResponse } from "./serviceClient"; export { QueryCollectionFormat } from "./queryCollectionFormat"; export { Constants } from "./util/constants"; export { logPolicy } from "./policies/logPolicy"; -export { BaseRequestPolicy, RequestPolicy, RequestPolicyFactory, RequestPolicyOptions, RequestPolicyOptionsLike } from "./policies/requestPolicy"; +export { + BaseRequestPolicy, + RequestPolicy, + RequestPolicyFactory, + RequestPolicyOptions, + RequestPolicyOptionsLike, +} from "./policies/requestPolicy"; export { generateClientRequestIdPolicy } from "./policies/generateClientRequestIdPolicy"; export { exponentialRetryPolicy } from "./policies/exponentialRetryPolicy"; export { systemErrorRetryPolicy } from "./policies/systemErrorRetryPolicy"; @@ -29,16 +49,38 @@ export { signingPolicy } from "./policies/signingPolicy"; export { userAgentPolicy, getDefaultUserAgentValue } from "./policies/userAgentPolicy"; export { deserializationPolicy, deserializeResponseBody } from "./policies/deserializationPolicy"; export { - MapperType, SimpleMapperType, CompositeMapperType, DictionaryMapperType, SequenceMapperType, EnumMapperType, - Mapper, BaseMapper, CompositeMapper, SequenceMapper, DictionaryMapper, EnumMapper, - MapperConstraints, PolymorphicDiscriminator, - Serializer, UrlParameterValue, serializeObject + MapperType, + SimpleMapperType, + CompositeMapperType, + DictionaryMapperType, + SequenceMapperType, + EnumMapperType, + Mapper, + BaseMapper, + CompositeMapper, + SequenceMapper, + DictionaryMapper, + EnumMapper, + MapperConstraints, + PolymorphicDiscriminator, + Serializer, + UrlParameterValue, + serializeObject, } from "./serializer"; export { - stripRequest, stripResponse, delay, - executePromisesSequentially, generateUuid, encodeUri, ServiceCallback, - promiseToCallback, promiseToServiceCallback, isValidUuid, - applyMixins, isNode, isDuration + stripRequest, + stripResponse, + delay, + executePromisesSequentially, + generateUuid, + encodeUri, + ServiceCallback, + promiseToCallback, + promiseToServiceCallback, + isValidUuid, + applyMixins, + isNode, + isDuration, } from "./util/utils"; export { URLBuilder, URLQuery } from "./url"; diff --git a/lib/nodeFetchHttpClient.ts b/lib/nodeFetchHttpClient.ts index 56f3508..343a102 100644 --- a/lib/nodeFetchHttpClient.ts +++ b/lib/nodeFetchHttpClient.ts @@ -21,7 +21,6 @@ if (typeof globalWithFetch.fetch !== "function") { globalWithFetch.fetch = fetch; } - export class NodeFetchHttpClient extends FetchHttpClient { private readonly cookieJar = new tough.CookieJar(undefined, { looseMode: true }); @@ -47,14 +46,18 @@ export class NodeFetchHttpClient extends FetchHttpClient { } if (httpRequest.agentSettings) { - const {http: httpAgent, https: httpsAgent} = httpRequest.agentSettings; + const { http: httpAgent, https: httpsAgent } = httpRequest.agentSettings; if (httpsAgent && httpRequest.url.startsWith("https")) { requestInit.agent = httpsAgent; } else if (httpAgent) { requestInit.agent = httpAgent; } } else if (httpRequest.proxySettings) { - const tunnel: ProxyAgent = createProxyAgent(httpRequest.url, httpRequest.proxySettings, httpRequest.headers); + const tunnel: ProxyAgent = createProxyAgent( + httpRequest.url, + httpRequest.proxySettings, + httpRequest.headers + ); requestInit.agent = tunnel.agent; } @@ -63,7 +66,9 @@ export class NodeFetchHttpClient extends FetchHttpClient { requestInit.agent.keepAlive = true; } else { const options: http.AgentOptions | https.AgentOptions = { keepAlive: true }; - const agent = httpRequest.url.startsWith("https") ? new https.Agent(options) : new http.Agent(options); + const agent = httpRequest.url.startsWith("https") + ? new https.Agent(options) + : new http.Agent(options); requestInit.agent = agent; } } @@ -80,13 +85,14 @@ export class NodeFetchHttpClient extends FetchHttpClient { setCookieHeader, operationResponse.request.url, { ignoreError: true }, - err => { + (err) => { if (err) { reject(err); } else { resolve(); } - }); + } + ); }); } } diff --git a/lib/operationArguments.ts b/lib/operationArguments.ts index b3420a4..55090db 100644 --- a/lib/operationArguments.ts +++ b/lib/operationArguments.ts @@ -16,4 +16,4 @@ export interface OperationArguments { * The optional arugments that are provided to an operation. */ options?: RequestOptionsBase; -} \ No newline at end of file +} diff --git a/lib/operationParameter.ts b/lib/operationParameter.ts index f99c69a..150b18a 100644 --- a/lib/operationParameter.ts +++ b/lib/operationParameter.ts @@ -58,7 +58,10 @@ export function getPathStringFromParameter(parameter: OperationParameter): strin return getPathStringFromParameterPath(parameter.parameterPath, parameter.mapper); } -export function getPathStringFromParameterPath(parameterPath: ParameterPath, mapper: Mapper): string { +export function getPathStringFromParameterPath( + parameterPath: ParameterPath, + mapper: Mapper +): string { let result: string; if (typeof parameterPath === "string") { result = parameterPath; @@ -68,4 +71,4 @@ export function getPathStringFromParameterPath(parameterPath: ParameterPath, map result = mapper.serializedName!; } return result; -} \ No newline at end of file +} diff --git a/lib/operationResponse.ts b/lib/operationResponse.ts index a3576eb..0fbea88 100644 --- a/lib/operationResponse.ts +++ b/lib/operationResponse.ts @@ -16,4 +16,4 @@ export interface OperationResponse { * The mapper that will be used to deserialize the response body. */ bodyMapper?: Mapper; -} \ No newline at end of file +} diff --git a/lib/operationSpec.ts b/lib/operationSpec.ts index 43c61ea..fe8b84a 100644 --- a/lib/operationSpec.ts +++ b/lib/operationSpec.ts @@ -1,7 +1,11 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. See License.txt in the project root for license information. -import { OperationParameter, OperationQueryParameter, OperationURLParameter } from "./operationParameter"; +import { + OperationParameter, + OperationQueryParameter, + OperationURLParameter, +} from "./operationParameter"; import { OperationResponse } from "./operationResponse"; import { MapperType, Serializer } from "./serializer"; import { HttpMethods } from "./webResource"; @@ -82,10 +86,13 @@ export function isStreamOperation(operationSpec: OperationSpec): boolean { let result = false; for (const statusCode in operationSpec.responses) { const operationResponse: OperationResponse = operationSpec.responses[statusCode]; - if (operationResponse.bodyMapper && operationResponse.bodyMapper.type.name === MapperType.Stream) { + if ( + operationResponse.bodyMapper && + operationResponse.bodyMapper.type.name === MapperType.Stream + ) { result = true; break; } } return result; -} \ No newline at end of file +} diff --git a/lib/policies/agentPolicy.browser.ts b/lib/policies/agentPolicy.browser.ts index 840cdcb..cca7184 100644 --- a/lib/policies/agentPolicy.browser.ts +++ b/lib/policies/agentPolicy.browser.ts @@ -2,7 +2,12 @@ // Licensed under the MIT License. See License.txt in the project root for license information. import { AgentSettings } from "../serviceClient"; -import { BaseRequestPolicy, RequestPolicy, RequestPolicyFactory, RequestPolicyOptionsLike } from "./requestPolicy"; +import { + BaseRequestPolicy, + RequestPolicy, + RequestPolicyFactory, + RequestPolicyOptionsLike, +} from "./requestPolicy"; import { HttpOperationResponse } from "../httpOperationResponse"; import { WebResourceLike } from "../webResource"; @@ -12,7 +17,7 @@ export function agentPolicy(_agentSettings?: AgentSettings): RequestPolicyFactor return { create: (_nextPolicy: RequestPolicy, _options: RequestPolicyOptionsLike) => { throw agentNotSupportedInBrowser; - } + }, }; } diff --git a/lib/policies/agentPolicy.ts b/lib/policies/agentPolicy.ts index 46d399b..624a14b 100644 --- a/lib/policies/agentPolicy.ts +++ b/lib/policies/agentPolicy.ts @@ -2,7 +2,12 @@ // Licensed under the MIT License. See License.txt in the project root for license information. import { AgentSettings } from "../serviceClient"; -import { BaseRequestPolicy, RequestPolicy, RequestPolicyFactory, RequestPolicyOptionsLike } from "./requestPolicy"; +import { + BaseRequestPolicy, + RequestPolicy, + RequestPolicyFactory, + RequestPolicyOptionsLike, +} from "./requestPolicy"; import { HttpOperationResponse } from "../httpOperationResponse"; import { WebResourceLike } from "../webResource"; @@ -10,14 +15,18 @@ export function agentPolicy(agentSettings?: AgentSettings): RequestPolicyFactory return { create: (nextPolicy: RequestPolicy, options: RequestPolicyOptionsLike) => { return new AgentPolicy(nextPolicy, options, agentSettings!); - } + }, }; } export class AgentPolicy extends BaseRequestPolicy { agentSettings: AgentSettings; - constructor(nextPolicy: RequestPolicy, options: RequestPolicyOptionsLike, agentSettings: AgentSettings) { + constructor( + nextPolicy: RequestPolicy, + options: RequestPolicyOptionsLike, + agentSettings: AgentSettings + ) { super(nextPolicy, options); this.agentSettings = agentSettings; } diff --git a/lib/policies/deserializationPolicy.ts b/lib/policies/deserializationPolicy.ts index 986a4fe..f14f78c 100644 --- a/lib/policies/deserializationPolicy.ts +++ b/lib/policies/deserializationPolicy.ts @@ -9,7 +9,12 @@ import { Mapper, MapperType } from "../serializer"; import * as utils from "../util/utils"; import { parseXML } from "../util/xml"; import { WebResourceLike } from "../webResource"; -import { BaseRequestPolicy, RequestPolicy, RequestPolicyFactory, RequestPolicyOptionsLike } from "./requestPolicy"; +import { + BaseRequestPolicy, + RequestPolicy, + RequestPolicyFactory, + RequestPolicyOptionsLike, +} from "./requestPolicy"; /** * The content-types that will indicate that an operation response should be deserialized in a @@ -33,11 +38,13 @@ export interface DeserializationContentTypes { * Create a new serialization RequestPolicyCreator that will serialized HTTP request bodies as they * pass through the HTTP pipeline. */ -export function deserializationPolicy(deserializationContentTypes?: DeserializationContentTypes): RequestPolicyFactory { +export function deserializationPolicy( + deserializationContentTypes?: DeserializationContentTypes +): RequestPolicyFactory { return { create: (nextPolicy: RequestPolicy, options: RequestPolicyOptionsLike) => { return new DeserializationPolicy(nextPolicy, deserializationContentTypes, options); - } + }, }; } @@ -52,24 +59,41 @@ export class DeserializationPolicy extends BaseRequestPolicy { public readonly jsonContentTypes: string[]; public readonly xmlContentTypes: string[]; - constructor(nextPolicy: RequestPolicy, deserializationContentTypes: DeserializationContentTypes | undefined, options: RequestPolicyOptionsLike) { + constructor( + nextPolicy: RequestPolicy, + deserializationContentTypes: DeserializationContentTypes | undefined, + options: RequestPolicyOptionsLike + ) { super(nextPolicy, options); - this.jsonContentTypes = deserializationContentTypes && deserializationContentTypes.json || defaultJsonContentTypes; - this.xmlContentTypes = deserializationContentTypes && deserializationContentTypes.xml || defaultXmlContentTypes; + this.jsonContentTypes = + (deserializationContentTypes && deserializationContentTypes.json) || defaultJsonContentTypes; + this.xmlContentTypes = + (deserializationContentTypes && deserializationContentTypes.xml) || defaultXmlContentTypes; } public async sendRequest(request: WebResourceLike): Promise { - return this._nextPolicy.sendRequest(request).then((response: HttpOperationResponse) => deserializeResponseBody(this.jsonContentTypes, this.xmlContentTypes, response)); + return this._nextPolicy + .sendRequest(request) + .then((response: HttpOperationResponse) => + deserializeResponseBody(this.jsonContentTypes, this.xmlContentTypes, response) + ); } } -function getOperationResponse(parsedResponse: HttpOperationResponse): undefined | OperationResponse { +function getOperationResponse( + parsedResponse: HttpOperationResponse +): undefined | OperationResponse { let result: OperationResponse | undefined; const request: WebResourceLike = parsedResponse.request; const operationSpec: OperationSpec | undefined = request.operationSpec; if (operationSpec) { - const operationResponseGetter: undefined | ((operationSpec: OperationSpec, response: HttpOperationResponse) => (undefined | OperationResponse)) = request.operationResponseGetter; + const operationResponseGetter: + | undefined + | (( + operationSpec: OperationSpec, + response: HttpOperationResponse + ) => undefined | OperationResponse) = request.operationResponseGetter; if (!operationResponseGetter) { result = operationSpec.responses[parsedResponse.status]; } else { @@ -80,7 +104,8 @@ function getOperationResponse(parsedResponse: HttpOperationResponse): undefined } function shouldDeserializeResponse(parsedResponse: HttpOperationResponse): boolean { - const shouldDeserialize: undefined | boolean | ((response: HttpOperationResponse) => boolean) = parsedResponse.request.shouldDeserialize; + const shouldDeserialize: undefined | boolean | ((response: HttpOperationResponse) => boolean) = + parsedResponse.request.shouldDeserialize; let result: boolean; if (shouldDeserialize === undefined) { result = true; @@ -92,8 +117,12 @@ function shouldDeserializeResponse(parsedResponse: HttpOperationResponse): boole return result; } -export function deserializeResponseBody(jsonContentTypes: string[], xmlContentTypes: string[], response: HttpOperationResponse): Promise { - return parse(jsonContentTypes, xmlContentTypes, response).then(parsedResponse => { +export function deserializeResponseBody( + jsonContentTypes: string[], + xmlContentTypes: string[], + response: HttpOperationResponse +): Promise { + return parse(jsonContentTypes, xmlContentTypes, response).then((parsedResponse) => { const shouldDeserialize: boolean = shouldDeserializeResponse(parsedResponse); if (shouldDeserialize) { const operationSpec: OperationSpec | undefined = parsedResponse.request.operationSpec; @@ -102,17 +131,21 @@ export function deserializeResponseBody(jsonContentTypes: string[], xmlContentTy const expectedStatusCodes: string[] = Object.keys(operationSpec.responses); - const hasNoExpectedStatusCodes: boolean = (expectedStatusCodes.length === 0 || (expectedStatusCodes.length === 1 && expectedStatusCodes[0] === "default")); + const hasNoExpectedStatusCodes: boolean = + expectedStatusCodes.length === 0 || + (expectedStatusCodes.length === 1 && expectedStatusCodes[0] === "default"); const responseSpec: OperationResponse | undefined = getOperationResponse(parsedResponse); - const isExpectedStatusCode: boolean = hasNoExpectedStatusCodes ? (200 <= statusCode && statusCode < 300) : !!responseSpec; + const isExpectedStatusCode: boolean = hasNoExpectedStatusCodes + ? 200 <= statusCode && statusCode < 300 + : !!responseSpec; if (!isExpectedStatusCode) { const defaultResponseSpec: OperationResponse = operationSpec.responses.default; if (defaultResponseSpec) { const initialErrorMessage: string = isStreamOperation(operationSpec) ? `Unexpected status code: ${statusCode}` - : parsedResponse.bodyAsText as string; + : (parsedResponse.bodyAsText as string); const error = new RestError(initialErrorMessage); error.statusCode = statusCode; @@ -122,8 +155,12 @@ export function deserializeResponseBody(jsonContentTypes: string[], xmlContentTy let parsedErrorResponse: { [key: string]: any } = parsedResponse.parsedBody; try { if (parsedErrorResponse) { - const defaultResponseBodyMapper: Mapper | undefined = defaultResponseSpec.bodyMapper; - if (defaultResponseBodyMapper && defaultResponseBodyMapper.serializedName === "CloudError") { + const defaultResponseBodyMapper: Mapper | undefined = + defaultResponseSpec.bodyMapper; + if ( + defaultResponseBodyMapper && + defaultResponseBodyMapper.serializedName === "CloudError" + ) { if (parsedErrorResponse.error) { parsedErrorResponse = parsedErrorResponse.error; } @@ -147,12 +184,20 @@ export function deserializeResponseBody(jsonContentTypes: string[], xmlContentTy if (defaultResponseBodyMapper) { let valueToDeserialize: any = parsedErrorResponse; - if (operationSpec.isXML && defaultResponseBodyMapper.type.name === MapperType.Sequence) { - valueToDeserialize = typeof parsedErrorResponse === "object" - ? parsedErrorResponse[defaultResponseBodyMapper.xmlElementName!] - : []; + if ( + operationSpec.isXML && + defaultResponseBodyMapper.type.name === MapperType.Sequence + ) { + valueToDeserialize = + typeof parsedErrorResponse === "object" + ? parsedErrorResponse[defaultResponseBodyMapper.xmlElementName!] + : []; } - error.body = operationSpec.serializer.deserialize(defaultResponseBodyMapper, valueToDeserialize, "error.body"); + error.body = operationSpec.serializer.deserialize( + defaultResponseBodyMapper, + valueToDeserialize, + "error.body" + ); } } } catch (defaultError) { @@ -164,12 +209,21 @@ export function deserializeResponseBody(jsonContentTypes: string[], xmlContentTy if (responseSpec.bodyMapper) { let valueToDeserialize: any = parsedResponse.parsedBody; if (operationSpec.isXML && responseSpec.bodyMapper.type.name === MapperType.Sequence) { - valueToDeserialize = typeof valueToDeserialize === "object" ? valueToDeserialize[responseSpec.bodyMapper.xmlElementName!] : []; + valueToDeserialize = + typeof valueToDeserialize === "object" + ? valueToDeserialize[responseSpec.bodyMapper.xmlElementName!] + : []; } try { - parsedResponse.parsedBody = operationSpec.serializer.deserialize(responseSpec.bodyMapper, valueToDeserialize, "operationRes.parsedBody"); + parsedResponse.parsedBody = operationSpec.serializer.deserialize( + responseSpec.bodyMapper, + valueToDeserialize, + "operationRes.parsedBody" + ); } catch (error) { - const restError = new RestError(`Error ${error} occurred in deserializing the responseBody - ${parsedResponse.bodyAsText}`); + const restError = new RestError( + `Error ${error} occurred in deserializing the responseBody - ${parsedResponse.bodyAsText}` + ); restError.request = utils.stripRequest(parsedResponse.request); restError.response = utils.stripResponse(parsedResponse); return Promise.reject(restError); @@ -180,7 +234,11 @@ export function deserializeResponseBody(jsonContentTypes: string[], xmlContentTy } if (responseSpec.headersMapper) { - parsedResponse.parsedHeaders = operationSpec.serializer.deserialize(responseSpec.headersMapper, parsedResponse.headers.rawHeaders(), "operationRes.parsedHeaders"); + parsedResponse.parsedHeaders = operationSpec.serializer.deserialize( + responseSpec.headersMapper, + parsedResponse.headers.rawHeaders(), + "operationRes.parsedHeaders" + ); } } } @@ -189,26 +247,42 @@ export function deserializeResponseBody(jsonContentTypes: string[], xmlContentTy }); } -function parse(jsonContentTypes: string[], xmlContentTypes: string[], operationResponse: HttpOperationResponse): Promise { +function parse( + jsonContentTypes: string[], + xmlContentTypes: string[], + operationResponse: HttpOperationResponse +): Promise { const errorHandler = (err: Error & { code: string }) => { const msg = `Error "${err}" occurred while parsing the response body - ${operationResponse.bodyAsText}.`; const errCode = err.code || RestError.PARSE_ERROR; - const e = new RestError(msg, errCode, operationResponse.status, operationResponse.request, operationResponse, operationResponse.bodyAsText); + const e = new RestError( + msg, + errCode, + operationResponse.status, + operationResponse.request, + operationResponse, + operationResponse.bodyAsText + ); return Promise.reject(e); }; if (!operationResponse.request.streamResponseBody && operationResponse.bodyAsText) { const text = operationResponse.bodyAsText; const contentType: string = operationResponse.headers.get("Content-Type") || ""; - const contentComponents: string[] = !contentType ? [] : contentType.split(";").map(component => component.toLowerCase()); - if (contentComponents.length === 0 || contentComponents.some(component => jsonContentTypes.indexOf(component) !== -1)) { - return new Promise(resolve => { + const contentComponents: string[] = !contentType + ? [] + : contentType.split(";").map((component) => component.toLowerCase()); + if ( + contentComponents.length === 0 || + contentComponents.some((component) => jsonContentTypes.indexOf(component) !== -1) + ) { + return new Promise((resolve) => { operationResponse.parsedBody = JSON.parse(text); resolve(operationResponse); }).catch(errorHandler); - } else if (contentComponents.some(component => xmlContentTypes.indexOf(component) !== -1)) { + } else if (contentComponents.some((component) => xmlContentTypes.indexOf(component) !== -1)) { return parseXML(text) - .then(body => { + .then((body) => { operationResponse.parsedBody = body; return operationResponse; }) @@ -217,4 +291,4 @@ function parse(jsonContentTypes: string[], xmlContentTypes: string[], operationR } return Promise.resolve(operationResponse); -} \ No newline at end of file +} diff --git a/lib/policies/exponentialRetryPolicy.ts b/lib/policies/exponentialRetryPolicy.ts index 28f2b1b..74aeb60 100644 --- a/lib/policies/exponentialRetryPolicy.ts +++ b/lib/policies/exponentialRetryPolicy.ts @@ -4,7 +4,12 @@ import { HttpOperationResponse } from "../httpOperationResponse"; import * as utils from "../util/utils"; import { WebResourceLike } from "../webResource"; -import { BaseRequestPolicy, RequestPolicy, RequestPolicyFactory, RequestPolicyOptionsLike } from "./requestPolicy"; +import { + BaseRequestPolicy, + RequestPolicy, + RequestPolicyFactory, + RequestPolicyOptionsLike, +} from "./requestPolicy"; import { RestError } from "../restError"; export interface RetryData { @@ -19,11 +24,23 @@ export interface RetryError extends Error { innerError?: RetryError; } -export function exponentialRetryPolicy(retryCount?: number, retryInterval?: number, minRetryInterval?: number, maxRetryInterval?: number): RequestPolicyFactory { +export function exponentialRetryPolicy( + retryCount?: number, + retryInterval?: number, + minRetryInterval?: number, + maxRetryInterval?: number +): RequestPolicyFactory { return { create: (nextPolicy: RequestPolicy, options: RequestPolicyOptionsLike) => { - return new ExponentialRetryPolicy(nextPolicy, options, retryCount, retryInterval, minRetryInterval, maxRetryInterval); - } + return new ExponentialRetryPolicy( + nextPolicy, + options, + retryCount, + retryInterval, + minRetryInterval, + maxRetryInterval + ); + }, }; } @@ -63,19 +80,33 @@ export class ExponentialRetryPolicy extends BaseRequestPolicy { * @param {number} [minRetryInterval] The minimum retry interval, in milliseconds. * @param {number} [maxRetryInterval] The maximum retry interval, in milliseconds. */ - constructor(nextPolicy: RequestPolicy, options: RequestPolicyOptionsLike, retryCount?: number, retryInterval?: number, minRetryInterval?: number, maxRetryInterval?: number) { + constructor( + nextPolicy: RequestPolicy, + options: RequestPolicyOptionsLike, + retryCount?: number, + retryInterval?: number, + minRetryInterval?: number, + maxRetryInterval?: number + ) { super(nextPolicy, options); - function isNumber(n: any): n is number { return typeof n === "number"; } + function isNumber(n: any): n is number { + return typeof n === "number"; + } this.retryCount = isNumber(retryCount) ? retryCount : DEFAULT_CLIENT_RETRY_COUNT; this.retryInterval = isNumber(retryInterval) ? retryInterval : DEFAULT_CLIENT_RETRY_INTERVAL; - this.minRetryInterval = isNumber(minRetryInterval) ? minRetryInterval : DEFAULT_CLIENT_MIN_RETRY_INTERVAL; - this.maxRetryInterval = isNumber(maxRetryInterval) ? maxRetryInterval : DEFAULT_CLIENT_MAX_RETRY_INTERVAL; + this.minRetryInterval = isNumber(minRetryInterval) + ? minRetryInterval + : DEFAULT_CLIENT_MIN_RETRY_INTERVAL; + this.maxRetryInterval = isNumber(maxRetryInterval) + ? maxRetryInterval + : DEFAULT_CLIENT_MAX_RETRY_INTERVAL; } public sendRequest(request: WebResourceLike): Promise { - return this._nextPolicy.sendRequest(request.clone()) - .then(response => retry(this, request, response)) - .catch(error => retry(this, request, error.response, undefined, error)); + return this._nextPolicy + .sendRequest(request.clone()) + .then((response) => retry(this, request, response)) + .catch((error) => retry(this, request, error.response, undefined, error)); } } @@ -87,8 +118,17 @@ export class ExponentialRetryPolicy extends BaseRequestPolicy { * @param {RetryData} retryData The retry data. * @return {boolean} True if the operation qualifies for a retry; false otherwise. */ -function shouldRetry(policy: ExponentialRetryPolicy, statusCode: number | undefined, retryData: RetryData): boolean { - if (statusCode == undefined || (statusCode < 500 && statusCode !== 408) || statusCode === 501 || statusCode === 505) { +function shouldRetry( + policy: ExponentialRetryPolicy, + statusCode: number | undefined, + retryData: RetryData +): boolean { + if ( + statusCode == undefined || + (statusCode < 500 && statusCode !== 408) || + statusCode === 501 || + statusCode === 505 + ) { return false; } @@ -96,10 +136,10 @@ function shouldRetry(policy: ExponentialRetryPolicy, statusCode: number | undefi if (!retryData) { throw new Error("retryData for the ExponentialRetryPolicyFilter cannot be null."); } else { - currentCount = (retryData && retryData.retryCount); + currentCount = retryData && retryData.retryCount; } - return (currentCount < policy.retryCount); + return currentCount < policy.retryCount; } /** @@ -109,11 +149,15 @@ function shouldRetry(policy: ExponentialRetryPolicy, statusCode: number | undefi * @param {RetryData} retryData The retry data. * @param {RetryError} [err] The operation"s error, if any. */ -function updateRetryData(policy: ExponentialRetryPolicy, retryData?: RetryData, err?: RetryError): RetryData { +function updateRetryData( + policy: ExponentialRetryPolicy, + retryData?: RetryData, + err?: RetryError +): RetryData { if (!retryData) { retryData = { retryCount: 0, - retryInterval: 0 + retryInterval: 0, }; } @@ -130,34 +174,47 @@ function updateRetryData(policy: ExponentialRetryPolicy, retryData?: RetryData, // Adjust retry interval let incrementDelta = Math.pow(2, retryData.retryCount) - 1; - const boundedRandDelta = policy.retryInterval * 0.8 + + const boundedRandDelta = + policy.retryInterval * 0.8 + Math.floor(Math.random() * (policy.retryInterval * 1.2 - policy.retryInterval * 0.8)); incrementDelta *= boundedRandDelta; - retryData.retryInterval = Math.min(policy.minRetryInterval + incrementDelta, policy.maxRetryInterval); + retryData.retryInterval = Math.min( + policy.minRetryInterval + incrementDelta, + policy.maxRetryInterval + ); return retryData; } -function retry(policy: ExponentialRetryPolicy, request: WebResourceLike, response?: HttpOperationResponse, retryData?: RetryData, requestError?: RetryError): Promise { +function retry( + policy: ExponentialRetryPolicy, + request: WebResourceLike, + response?: HttpOperationResponse, + retryData?: RetryData, + requestError?: RetryError +): Promise { retryData = updateRetryData(policy, retryData, requestError); const isAborted: boolean | undefined = request.abortSignal && request.abortSignal.aborted; if (!isAborted && shouldRetry(policy, response && response.status, retryData)) { - return utils.delay(retryData.retryInterval) + return utils + .delay(retryData.retryInterval) .then(() => policy._nextPolicy.sendRequest(request.clone())) - .then(res => retry(policy, request, res, retryData, undefined)) - .catch(err => retry(policy, request, response, retryData, err)); + .then((res) => retry(policy, request, res, retryData, undefined)) + .catch((err) => retry(policy, request, response, retryData, err)); } else if (isAborted || requestError || !response) { // If the operation failed in the end, return all errors instead of just the last one - const err = retryData.error || + const err = + retryData.error || new RestError( "Failed to send the request.", RestError.REQUEST_SEND_ERROR, response && response.status, response && response.request, - response); + response + ); return Promise.reject(err); } else { return Promise.resolve(response); } -} \ No newline at end of file +} diff --git a/lib/policies/generateClientRequestIdPolicy.ts b/lib/policies/generateClientRequestIdPolicy.ts index ef57012..aa17a31 100644 --- a/lib/policies/generateClientRequestIdPolicy.ts +++ b/lib/policies/generateClientRequestIdPolicy.ts @@ -4,18 +4,29 @@ import { HttpOperationResponse } from "../httpOperationResponse"; import * as utils from "../util/utils"; import { WebResourceLike } from "../webResource"; -import { BaseRequestPolicy, RequestPolicy, RequestPolicyFactory, RequestPolicyOptionsLike } from "./requestPolicy"; +import { + BaseRequestPolicy, + RequestPolicy, + RequestPolicyFactory, + RequestPolicyOptionsLike, +} from "./requestPolicy"; -export function generateClientRequestIdPolicy(requestIdHeaderName = "x-ms-client-request-id"): RequestPolicyFactory { +export function generateClientRequestIdPolicy( + requestIdHeaderName = "x-ms-client-request-id" +): RequestPolicyFactory { return { create: (nextPolicy: RequestPolicy, options: RequestPolicyOptionsLike) => { return new GenerateClientRequestIdPolicy(nextPolicy, options, requestIdHeaderName); - } + }, }; } export class GenerateClientRequestIdPolicy extends BaseRequestPolicy { - constructor(nextPolicy: RequestPolicy, options: RequestPolicyOptionsLike, private _requestIdHeaderName: string) { + constructor( + nextPolicy: RequestPolicy, + options: RequestPolicyOptionsLike, + private _requestIdHeaderName: string + ) { super(nextPolicy, options); } diff --git a/lib/policies/logPolicy.ts b/lib/policies/logPolicy.ts index 4f99b58..90d44ca 100644 --- a/lib/policies/logPolicy.ts +++ b/lib/policies/logPolicy.ts @@ -3,33 +3,45 @@ import { HttpOperationResponse } from "../httpOperationResponse"; import { WebResourceLike } from "../webResource"; -import { BaseRequestPolicy, RequestPolicy, RequestPolicyFactory, RequestPolicyOptionsLike } from "./requestPolicy"; +import { + BaseRequestPolicy, + RequestPolicy, + RequestPolicyFactory, + RequestPolicyOptionsLike, +} from "./requestPolicy"; export function logPolicy(logger: any = console.log): RequestPolicyFactory { return { create: (nextPolicy: RequestPolicy, options: RequestPolicyOptionsLike) => { return new LogPolicy(nextPolicy, options, logger); - } + }, }; } export class LogPolicy extends BaseRequestPolicy { logger?: any; - constructor(nextPolicy: RequestPolicy, options: RequestPolicyOptionsLike, logger: any = console.log) { + constructor( + nextPolicy: RequestPolicy, + options: RequestPolicyOptionsLike, + logger: any = console.log + ) { super(nextPolicy, options); this.logger = logger; } public sendRequest(request: WebResourceLike): Promise { - return this._nextPolicy.sendRequest(request).then(response => logResponse(this, response)); + return this._nextPolicy.sendRequest(request).then((response) => logResponse(this, response)); } } -function logResponse(policy: LogPolicy, response: HttpOperationResponse): Promise { +function logResponse( + policy: LogPolicy, + response: HttpOperationResponse +): Promise { policy.logger(`>> Request: ${JSON.stringify(response.request, undefined, 2)}`); policy.logger(`>> Response status code: ${response.status}`); const responseBody = response.bodyAsText; policy.logger(`>> Body: ${responseBody}`); return Promise.resolve(response); -} \ No newline at end of file +} diff --git a/lib/policies/msRestUserAgentPolicy.browser.ts b/lib/policies/msRestUserAgentPolicy.browser.ts index 04b7082..ec37b93 100644 --- a/lib/policies/msRestUserAgentPolicy.browser.ts +++ b/lib/policies/msRestUserAgentPolicy.browser.ts @@ -21,7 +21,7 @@ export function getPlatformSpecificData(): TelemetryInfo[] { const navigator = window.navigator as NavigatorEx; const osInfo = { key: "OS", - value: (navigator.oscpu || navigator.platform).replace(" ", "") + value: (navigator.oscpu || navigator.platform).replace(" ", ""), }; return [osInfo]; diff --git a/lib/policies/msRestUserAgentPolicy.ts b/lib/policies/msRestUserAgentPolicy.ts index 29de627..ea523dd 100644 --- a/lib/policies/msRestUserAgentPolicy.ts +++ b/lib/policies/msRestUserAgentPolicy.ts @@ -12,12 +12,12 @@ export function getDefaultUserAgentKey(): string { export function getPlatformSpecificData(): TelemetryInfo[] { const runtimeInfo = { key: "Node", - value: process.version + value: process.version, }; const osInfo = { key: "OS", - value: `(${os.arch()}-${os.type()}-${os.release()})` + value: `(${os.arch()}-${os.type()}-${os.release()})`, }; return [runtimeInfo, osInfo]; diff --git a/lib/policies/proxyPolicy.browser.ts b/lib/policies/proxyPolicy.browser.ts index 898bc9c..a1c194d 100644 --- a/lib/policies/proxyPolicy.browser.ts +++ b/lib/policies/proxyPolicy.browser.ts @@ -2,7 +2,12 @@ // Licensed under the MIT License. See License.txt in the project root for license information. import { ProxySettings } from "../serviceClient"; -import { BaseRequestPolicy, RequestPolicy, RequestPolicyFactory, RequestPolicyOptionsLike } from "./requestPolicy"; +import { + BaseRequestPolicy, + RequestPolicy, + RequestPolicyFactory, + RequestPolicyOptionsLike, +} from "./requestPolicy"; import { HttpOperationResponse } from "../httpOperationResponse"; import { WebResourceLike } from "../webResource"; @@ -16,7 +21,7 @@ export function proxyPolicy(_proxySettings?: ProxySettings): RequestPolicyFactor return { create: (_nextPolicy: RequestPolicy, _options: RequestPolicyOptionsLike) => { throw proxyNotSupportedInBrowser; - } + }, }; } diff --git a/lib/policies/proxyPolicy.ts b/lib/policies/proxyPolicy.ts index eaeb876..194d9f4 100644 --- a/lib/policies/proxyPolicy.ts +++ b/lib/policies/proxyPolicy.ts @@ -1,7 +1,12 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. See License.txt in the project root for license information. -import { BaseRequestPolicy, RequestPolicy, RequestPolicyFactory, RequestPolicyOptionsLike } from "./requestPolicy"; +import { + BaseRequestPolicy, + RequestPolicy, + RequestPolicyFactory, + RequestPolicyOptionsLike, +} from "./requestPolicy"; import { HttpOperationResponse } from "../httpOperationResponse"; import { ProxySettings } from "../serviceClient"; import { WebResourceLike } from "../webResource"; @@ -37,23 +42,26 @@ export function getDefaultProxySettings(proxyUrl?: string): ProxySettings | unde const parsedUrl = URLBuilder.parse(proxyUrl); return { host: parsedUrl.getScheme() + "://" + parsedUrl.getHost(), - port: Number.parseInt(parsedUrl.getPort() || "80") + port: Number.parseInt(parsedUrl.getPort() || "80"), }; } - export function proxyPolicy(proxySettings?: ProxySettings): RequestPolicyFactory { return { create: (nextPolicy: RequestPolicy, options: RequestPolicyOptionsLike) => { return new ProxyPolicy(nextPolicy, options, proxySettings!); - } + }, }; } export class ProxyPolicy extends BaseRequestPolicy { proxySettings: ProxySettings; - constructor(nextPolicy: RequestPolicy, options: RequestPolicyOptionsLike, proxySettings: ProxySettings) { + constructor( + nextPolicy: RequestPolicy, + options: RequestPolicyOptionsLike, + proxySettings: ProxySettings + ) { super(nextPolicy, options); this.proxySettings = proxySettings; } diff --git a/lib/policies/redirectPolicy.ts b/lib/policies/redirectPolicy.ts index 885fe39..8d010fd 100644 --- a/lib/policies/redirectPolicy.ts +++ b/lib/policies/redirectPolicy.ts @@ -4,33 +4,49 @@ import { HttpOperationResponse } from "../httpOperationResponse"; import { URLBuilder } from "../url"; import { WebResourceLike } from "../webResource"; -import { BaseRequestPolicy, RequestPolicy, RequestPolicyFactory, RequestPolicyOptionsLike } from "./requestPolicy"; +import { + BaseRequestPolicy, + RequestPolicy, + RequestPolicyFactory, + RequestPolicyOptionsLike, +} from "./requestPolicy"; export function redirectPolicy(maximumRetries = 20): RequestPolicyFactory { return { create: (nextPolicy: RequestPolicy, options: RequestPolicyOptionsLike) => { return new RedirectPolicy(nextPolicy, options, maximumRetries); - } + }, }; } export class RedirectPolicy extends BaseRequestPolicy { - constructor(nextPolicy: RequestPolicy, options: RequestPolicyOptionsLike, readonly maxRetries = 20) { + constructor( + nextPolicy: RequestPolicy, + options: RequestPolicyOptionsLike, + readonly maxRetries = 20 + ) { super(nextPolicy, options); } public sendRequest(request: WebResourceLike): Promise { - return this._nextPolicy.sendRequest(request).then(response => handleRedirect(this, response, 0)); + return this._nextPolicy + .sendRequest(request) + .then((response) => handleRedirect(this, response, 0)); } } -function handleRedirect(policy: RedirectPolicy, response: HttpOperationResponse, currentRetries: number): Promise { +function handleRedirect( + policy: RedirectPolicy, + response: HttpOperationResponse, + currentRetries: number +): Promise { const { request, status } = response; const locationHeader = response.headers.get("location"); - if (locationHeader && + if ( + locationHeader && (status === 300 || status === 307 || (status === 303 && request.method === "POST")) && - (!policy.maxRetries || currentRetries < policy.maxRetries)) { - + (!policy.maxRetries || currentRetries < policy.maxRetries) + ) { const builder = URLBuilder.parse(request.url); builder.setPath(locationHeader); request.url = builder.toString(); @@ -41,9 +57,10 @@ function handleRedirect(policy: RedirectPolicy, response: HttpOperationResponse, request.method = "GET"; } - return policy._nextPolicy.sendRequest(request) - .then(res => handleRedirect(policy, res, currentRetries + 1)); + return policy._nextPolicy + .sendRequest(request) + .then((res) => handleRedirect(policy, res, currentRetries + 1)); } return Promise.resolve(response); -} \ No newline at end of file +} diff --git a/lib/policies/requestPolicy.ts b/lib/policies/requestPolicy.ts index 61167e3..d25d314 100644 --- a/lib/policies/requestPolicy.ts +++ b/lib/policies/requestPolicy.ts @@ -10,7 +10,7 @@ import { WebResourceLike } from "../webResource"; * Creates a new RequestPolicy per-request that uses the provided nextPolicy. */ export type RequestPolicyFactory = { - create(nextPolicy: RequestPolicy, options: RequestPolicyOptionsLike): RequestPolicy + create(nextPolicy: RequestPolicy, options: RequestPolicyOptionsLike): RequestPolicy; }; export interface RequestPolicy { @@ -18,8 +18,10 @@ export interface RequestPolicy { } export abstract class BaseRequestPolicy implements RequestPolicy { - protected constructor(readonly _nextPolicy: RequestPolicy, readonly _options: RequestPolicyOptionsLike) { - } + protected constructor( + readonly _nextPolicy: RequestPolicy, + readonly _options: RequestPolicyOptionsLike + ) {} public abstract sendRequest(webResource: WebResourceLike): Promise; @@ -67,8 +69,7 @@ export interface RequestPolicyOptionsLike { * Optional properties that can be used when creating a RequestPolicy. */ export class RequestPolicyOptions implements RequestPolicyOptionsLike { - constructor(private _logger?: HttpPipelineLogger) { - } + constructor(private _logger?: HttpPipelineLogger) {} /** * Get whether or not a log with the provided log level should be logged. @@ -76,9 +77,11 @@ export class RequestPolicyOptions implements RequestPolicyOptionsLike { * @returns Whether or not a log with the provided log level should be logged. */ public shouldLog(logLevel: HttpPipelineLogLevel): boolean { - return !!this._logger && + return ( + !!this._logger && logLevel !== HttpPipelineLogLevel.OFF && - logLevel <= this._logger.minimumLogLevel; + logLevel <= this._logger.minimumLogLevel + ); } /** @@ -92,4 +95,4 @@ export class RequestPolicyOptions implements RequestPolicyOptionsLike { this._logger.log(logLevel, message); } } -} \ No newline at end of file +} diff --git a/lib/policies/rpRegistrationPolicy.ts b/lib/policies/rpRegistrationPolicy.ts index e82a99b..47f11f3 100644 --- a/lib/policies/rpRegistrationPolicy.ts +++ b/lib/policies/rpRegistrationPolicy.ts @@ -3,47 +3,62 @@ import { HttpOperationResponse } from "../httpOperationResponse"; import * as utils from "../util/utils"; import { WebResourceLike } from "../webResource"; -import { BaseRequestPolicy, RequestPolicy, RequestPolicyFactory, RequestPolicyOptionsLike } from "./requestPolicy"; +import { + BaseRequestPolicy, + RequestPolicy, + RequestPolicyFactory, + RequestPolicyOptionsLike, +} from "./requestPolicy"; export function rpRegistrationPolicy(retryTimeout = 30): RequestPolicyFactory { return { create: (nextPolicy: RequestPolicy, options: RequestPolicyOptionsLike) => { return new RPRegistrationPolicy(nextPolicy, options, retryTimeout); - } + }, }; } export class RPRegistrationPolicy extends BaseRequestPolicy { - constructor(nextPolicy: RequestPolicy, options: RequestPolicyOptionsLike, readonly _retryTimeout = 30) { + constructor( + nextPolicy: RequestPolicy, + options: RequestPolicyOptionsLike, + readonly _retryTimeout = 30 + ) { super(nextPolicy, options); } public sendRequest(request: WebResourceLike): Promise { - return this._nextPolicy.sendRequest(request.clone()) - .then(response => registerIfNeeded(this, request, response)); + return this._nextPolicy + .sendRequest(request.clone()) + .then((response) => registerIfNeeded(this, request, response)); } } - -function registerIfNeeded(policy: RPRegistrationPolicy, request: WebResourceLike, response: HttpOperationResponse): Promise { +function registerIfNeeded( + policy: RPRegistrationPolicy, + request: WebResourceLike, + response: HttpOperationResponse +): Promise { if (response.status === 409) { const rpName = checkRPNotRegisteredError(response.bodyAsText as string); if (rpName) { const urlPrefix = extractSubscriptionUrl(request.url); - return registerRP(policy, urlPrefix, rpName, request) - // Autoregistration of ${provider} failed for some reason. We will not return this error - // instead will return the initial response with 409 status code back to the user. - // do nothing here as we are returning the original response at the end of this method. - .catch(() => false) - .then(registrationStatus => { - if (registrationStatus) { - // Retry the original request. We have to change the x-ms-client-request-id - // otherwise Azure endpoint will return the initial 409 (cached) response. - request.headers.set("x-ms-client-request-id", utils.generateUuid()); - return policy._nextPolicy.sendRequest(request.clone()); - } - return response; - }); + return ( + registerRP(policy, urlPrefix, rpName, request) + // Autoregistration of ${provider} failed for some reason. We will not return this error + // instead will return the initial response with 409 status code back to the user. + // do nothing here as we are returning the original response at the end of this method. + .catch(() => false) + .then((registrationStatus) => { + if (registrationStatus) { + // Retry the original request. We have to change the x-ms-client-request-id + // otherwise Azure endpoint will return the initial 409 (cached) response. + request.headers.set("x-ms-client-request-id", utils.generateUuid()); + return policy._nextPolicy.sendRequest(request.clone()); + } + return response; + }) + ); } } @@ -56,7 +71,10 @@ function registerIfNeeded(policy: RPRegistrationPolicy, request: WebResourceLike * @param {boolean} reuseUrlToo Should the url from the original request be reused as well. Default false. * @returns {object} A new request object with desired headers. */ -function getRequestEssentials(originalRequest: WebResourceLike, reuseUrlToo = false): WebResourceLike { +function getRequestEssentials( + originalRequest: WebResourceLike, + reuseUrlToo = false +): WebResourceLike { const reqOptions: WebResourceLike = originalRequest.clone(); if (reuseUrlToo) { reqOptions.url = originalRequest.url; @@ -86,8 +104,13 @@ function checkRPNotRegisteredError(body: string): string { } catch (err) { // do nothing; } - if (responseBody && responseBody.error && responseBody.error.message && - responseBody.error.code && responseBody.error.code === "MissingSubscriptionRegistration") { + if ( + responseBody && + responseBody.error && + responseBody.error.message && + responseBody.error.code && + responseBody.error.code === "MissingSubscriptionRegistration" + ) { const matchRes = responseBody.error.message.match(/.*'(.*)'/i); if (matchRes) { result = matchRes.pop(); @@ -105,7 +128,7 @@ function checkRPNotRegisteredError(body: string): string { */ function extractSubscriptionUrl(url: string): string { let result; - const matchRes = url.match(/.*\/subscriptions\/[a-f0-9-]+\//ig); + const matchRes = url.match(/.*\/subscriptions\/[a-f0-9-]+\//gi); if (matchRes && matchRes[0]) { result = matchRes[0]; } else { @@ -123,20 +146,24 @@ function extractSubscriptionUrl(url: string): string { * with a message that the provider is not registered. * @param {registrationCallback} callback The callback that handles the RP registration */ -function registerRP(policy: RPRegistrationPolicy, urlPrefix: string, provider: string, originalRequest: WebResourceLike): Promise { +function registerRP( + policy: RPRegistrationPolicy, + urlPrefix: string, + provider: string, + originalRequest: WebResourceLike +): Promise { const postUrl = `${urlPrefix}providers/${provider}/register?api-version=2016-02-01`; const getUrl = `${urlPrefix}providers/${provider}?api-version=2016-02-01`; const reqOptions = getRequestEssentials(originalRequest); reqOptions.method = "POST"; reqOptions.url = postUrl; - return policy._nextPolicy.sendRequest(reqOptions) - .then(response => { - if (response.status !== 200) { - throw new Error(`Autoregistration of ${provider} failed. Please try registering manually.`); - } - return getRegistrationStatus(policy, getUrl, originalRequest); - }); + return policy._nextPolicy.sendRequest(reqOptions).then((response) => { + if (response.status !== 200) { + throw new Error(`Autoregistration of ${provider} failed. Please try registering manually.`); + } + return getRegistrationStatus(policy, getUrl, originalRequest); + }); } /** @@ -148,17 +175,23 @@ function registerRP(policy: RPRegistrationPolicy, urlPrefix: string, provider: s * with a message that the provider is not registered. * @returns {Promise} True if RP Registration is successful. */ -function getRegistrationStatus(policy: RPRegistrationPolicy, url: string, originalRequest: WebResourceLike): Promise { +function getRegistrationStatus( + policy: RPRegistrationPolicy, + url: string, + originalRequest: WebResourceLike +): Promise { const reqOptions: any = getRequestEssentials(originalRequest); reqOptions.url = url; reqOptions.method = "GET"; - return policy._nextPolicy.sendRequest(reqOptions).then(res => { - const obj = (res.parsedBody as any); + return policy._nextPolicy.sendRequest(reqOptions).then((res) => { + const obj = res.parsedBody as any; if (res.parsedBody && obj.registrationState && obj.registrationState === "Registered") { return true; } else { - return utils.delay(policy._retryTimeout * 1000).then(() => getRegistrationStatus(policy, url, originalRequest)); + return utils + .delay(policy._retryTimeout * 1000) + .then(() => getRegistrationStatus(policy, url, originalRequest)); } }); } diff --git a/lib/policies/signingPolicy.ts b/lib/policies/signingPolicy.ts index 82d36e6..91b3184 100644 --- a/lib/policies/signingPolicy.ts +++ b/lib/policies/signingPolicy.ts @@ -4,19 +4,29 @@ import { ServiceClientCredentials } from "../credentials/serviceClientCredentials"; import { HttpOperationResponse } from "../httpOperationResponse"; import { WebResourceLike } from "../webResource"; -import { BaseRequestPolicy, RequestPolicyFactory, RequestPolicy, RequestPolicyOptionsLike } from "./requestPolicy"; +import { + BaseRequestPolicy, + RequestPolicyFactory, + RequestPolicy, + RequestPolicyOptionsLike, +} from "./requestPolicy"; -export function signingPolicy(authenticationProvider: ServiceClientCredentials): RequestPolicyFactory { +export function signingPolicy( + authenticationProvider: ServiceClientCredentials +): RequestPolicyFactory { return { create: (nextPolicy: RequestPolicy, options: RequestPolicyOptionsLike) => { return new SigningPolicy(nextPolicy, options, authenticationProvider); - } + }, }; } export class SigningPolicy extends BaseRequestPolicy { - - constructor(nextPolicy: RequestPolicy, options: RequestPolicyOptionsLike, public authenticationProvider: ServiceClientCredentials) { + constructor( + nextPolicy: RequestPolicy, + options: RequestPolicyOptionsLike, + public authenticationProvider: ServiceClientCredentials + ) { super(nextPolicy, options); } @@ -25,6 +35,8 @@ export class SigningPolicy extends BaseRequestPolicy { } public sendRequest(request: WebResourceLike): Promise { - return this.signRequest(request).then(nextRequest => this._nextPolicy.sendRequest(nextRequest)); + return this.signRequest(request).then((nextRequest) => + this._nextPolicy.sendRequest(nextRequest) + ); } } diff --git a/lib/policies/systemErrorRetryPolicy.ts b/lib/policies/systemErrorRetryPolicy.ts index 1650fbe..18dc307 100644 --- a/lib/policies/systemErrorRetryPolicy.ts +++ b/lib/policies/systemErrorRetryPolicy.ts @@ -4,7 +4,12 @@ import { HttpOperationResponse } from "../httpOperationResponse"; import * as utils from "../util/utils"; import { WebResourceLike } from "../webResource"; -import { BaseRequestPolicy, RequestPolicy, RequestPolicyFactory, RequestPolicyOptionsLike } from "./requestPolicy"; +import { + BaseRequestPolicy, + RequestPolicy, + RequestPolicyFactory, + RequestPolicyOptionsLike, +} from "./requestPolicy"; export interface RetryData { retryCount: number; @@ -18,11 +23,23 @@ export interface RetryError extends Error { innerError?: RetryError; } -export function systemErrorRetryPolicy(retryCount?: number, retryInterval?: number, minRetryInterval?: number, maxRetryInterval?: number): RequestPolicyFactory { +export function systemErrorRetryPolicy( + retryCount?: number, + retryInterval?: number, + minRetryInterval?: number, + maxRetryInterval?: number +): RequestPolicyFactory { return { create: (nextPolicy: RequestPolicy, options: RequestPolicyOptionsLike) => { - return new SystemErrorRetryPolicy(nextPolicy, options, retryCount, retryInterval, minRetryInterval, maxRetryInterval); - } + return new SystemErrorRetryPolicy( + nextPolicy, + options, + retryCount, + retryInterval, + minRetryInterval, + maxRetryInterval + ); + }, }; } @@ -46,16 +63,32 @@ export class SystemErrorRetryPolicy extends BaseRequestPolicy { DEFAULT_CLIENT_MAX_RETRY_INTERVAL = 1000 * 90; DEFAULT_CLIENT_MIN_RETRY_INTERVAL = 1000 * 3; - constructor(nextPolicy: RequestPolicy, options: RequestPolicyOptionsLike, retryCount?: number, retryInterval?: number, minRetryInterval?: number, maxRetryInterval?: number) { + constructor( + nextPolicy: RequestPolicy, + options: RequestPolicyOptionsLike, + retryCount?: number, + retryInterval?: number, + minRetryInterval?: number, + maxRetryInterval?: number + ) { super(nextPolicy, options); this.retryCount = typeof retryCount === "number" ? retryCount : this.DEFAULT_CLIENT_RETRY_COUNT; - this.retryInterval = typeof retryInterval === "number" ? retryInterval : this.DEFAULT_CLIENT_RETRY_INTERVAL; - this.minRetryInterval = typeof minRetryInterval === "number" ? minRetryInterval : this.DEFAULT_CLIENT_MIN_RETRY_INTERVAL; - this.maxRetryInterval = typeof maxRetryInterval === "number" ? maxRetryInterval : this.DEFAULT_CLIENT_MAX_RETRY_INTERVAL; + this.retryInterval = + typeof retryInterval === "number" ? retryInterval : this.DEFAULT_CLIENT_RETRY_INTERVAL; + this.minRetryInterval = + typeof minRetryInterval === "number" + ? minRetryInterval + : this.DEFAULT_CLIENT_MIN_RETRY_INTERVAL; + this.maxRetryInterval = + typeof maxRetryInterval === "number" + ? maxRetryInterval + : this.DEFAULT_CLIENT_MAX_RETRY_INTERVAL; } public sendRequest(request: WebResourceLike): Promise { - return this._nextPolicy.sendRequest(request.clone()).then(response => retry(this, request, response)); + return this._nextPolicy + .sendRequest(request.clone()) + .then((response) => retry(this, request, response)); } } @@ -71,9 +104,9 @@ function shouldRetry(policy: SystemErrorRetryPolicy, retryData: RetryData): bool if (!retryData) { throw new Error("retryData for the SystemErrorRetryPolicyFilter cannot be null."); } else { - currentCount = (retryData && retryData.retryCount); + currentCount = retryData && retryData.retryCount; } - return (currentCount < policy.retryCount); + return currentCount < policy.retryCount; } /** @@ -82,11 +115,15 @@ function shouldRetry(policy: SystemErrorRetryPolicy, retryData: RetryData): bool * @param {RetryData} retryData The retry data. * @param {object} err The operation"s error, if any. */ -function updateRetryData(policy: SystemErrorRetryPolicy, retryData?: RetryData, err?: RetryError): RetryData { +function updateRetryData( + policy: SystemErrorRetryPolicy, + retryData?: RetryData, + err?: RetryError +): RetryData { if (!retryData) { retryData = { retryCount: 0, - retryInterval: 0 + retryInterval: 0, }; } @@ -103,25 +140,43 @@ function updateRetryData(policy: SystemErrorRetryPolicy, retryData?: RetryData, // Adjust retry interval let incrementDelta = Math.pow(2, retryData.retryCount) - 1; - const boundedRandDelta = policy.retryInterval * 0.8 + + const boundedRandDelta = + policy.retryInterval * 0.8 + Math.floor(Math.random() * (policy.retryInterval * 1.2 - policy.retryInterval * 0.8)); incrementDelta *= boundedRandDelta; - retryData.retryInterval = Math.min(policy.minRetryInterval + incrementDelta, policy.maxRetryInterval); + retryData.retryInterval = Math.min( + policy.minRetryInterval + incrementDelta, + policy.maxRetryInterval + ); return retryData; } -function retry(policy: SystemErrorRetryPolicy, request: WebResourceLike, operationResponse: HttpOperationResponse, retryData?: RetryData, err?: RetryError): Promise { +function retry( + policy: SystemErrorRetryPolicy, + request: WebResourceLike, + operationResponse: HttpOperationResponse, + retryData?: RetryData, + err?: RetryError +): Promise { retryData = updateRetryData(policy, retryData, err); - if (err && err.code && shouldRetry(policy, retryData) && - (err.code === "ETIMEDOUT" || err.code === "ESOCKETTIMEDOUT" || err.code === "ECONNREFUSED" || - err.code === "ECONNRESET" || err.code === "ENOENT")) { + if ( + err && + err.code && + shouldRetry(policy, retryData) && + (err.code === "ETIMEDOUT" || + err.code === "ESOCKETTIMEDOUT" || + err.code === "ECONNREFUSED" || + err.code === "ECONNRESET" || + err.code === "ENOENT") + ) { // If previous operation ended with an error and the policy allows a retry, do that - return utils.delay(retryData.retryInterval) - .then(() => policy._nextPolicy.sendRequest(request.clone())) - .then(res => retry(policy, request, res, retryData, err)) - .catch(err => retry(policy, request, operationResponse, retryData, err)); + return utils + .delay(retryData.retryInterval) + .then(() => policy._nextPolicy.sendRequest(request.clone())) + .then((res) => retry(policy, request, res, retryData, err)) + .catch((err) => retry(policy, request, operationResponse, retryData, err)); } else { if (err != undefined) { // If the operation failed in the end, return all errors instead of just the last one @@ -130,4 +185,4 @@ function retry(policy: SystemErrorRetryPolicy, request: WebResourceLike, operati } return Promise.resolve(operationResponse); } -} \ No newline at end of file +} diff --git a/lib/policies/throttlingRetryPolicy.ts b/lib/policies/throttlingRetryPolicy.ts index b8364b5..e1aac95 100644 --- a/lib/policies/throttlingRetryPolicy.ts +++ b/lib/policies/throttlingRetryPolicy.ts @@ -1,20 +1,28 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. See License.txt in the project root for license information. -import { BaseRequestPolicy, RequestPolicy, RequestPolicyOptionsLike, RequestPolicyFactory } from "./requestPolicy"; +import { + BaseRequestPolicy, + RequestPolicy, + RequestPolicyOptionsLike, + RequestPolicyFactory, +} from "./requestPolicy"; import { WebResourceLike } from "../webResource"; import { HttpOperationResponse } from "../httpOperationResponse"; import { Constants } from "../util/constants"; import { delay } from "../util/utils"; -type ResponseHandler = (httpRequest: WebResourceLike, response: HttpOperationResponse) => Promise; +type ResponseHandler = ( + httpRequest: WebResourceLike, + response: HttpOperationResponse +) => Promise; const StatusCodes = Constants.HttpConstants.StatusCodes; export function throttlingRetryPolicy(): RequestPolicyFactory { return { create: (nextPolicy: RequestPolicy, options: RequestPolicyOptionsLike) => { return new ThrottlingRetryPolicy(nextPolicy, options); - } + }, }; } @@ -27,13 +35,17 @@ export function throttlingRetryPolicy(): RequestPolicyFactory { export class ThrottlingRetryPolicy extends BaseRequestPolicy { private _handleResponse: ResponseHandler; - constructor(nextPolicy: RequestPolicy, options: RequestPolicyOptionsLike, _handleResponse?: ResponseHandler) { + constructor( + nextPolicy: RequestPolicy, + options: RequestPolicyOptionsLike, + _handleResponse?: ResponseHandler + ) { super(nextPolicy, options); this._handleResponse = _handleResponse || this._defaultResponseHandler; } public async sendRequest(httpRequest: WebResourceLike): Promise { - return this._nextPolicy.sendRequest(httpRequest.clone()).then(response => { + return this._nextPolicy.sendRequest(httpRequest.clone()).then((response) => { if (response.status !== StatusCodes.TooManyRequests) { return response; } else { @@ -42,11 +54,18 @@ export class ThrottlingRetryPolicy extends BaseRequestPolicy { }); } - private async _defaultResponseHandler(httpRequest: WebResourceLike, httpResponse: HttpOperationResponse): Promise { - const retryAfterHeader: string | undefined = httpResponse.headers.get(Constants.HeaderConstants.RETRY_AFTER); + private async _defaultResponseHandler( + httpRequest: WebResourceLike, + httpResponse: HttpOperationResponse + ): Promise { + const retryAfterHeader: string | undefined = httpResponse.headers.get( + Constants.HeaderConstants.RETRY_AFTER + ); if (retryAfterHeader) { - const delayInMs: number | undefined = ThrottlingRetryPolicy.parseRetryAfterHeader(retryAfterHeader); + const delayInMs: number | undefined = ThrottlingRetryPolicy.parseRetryAfterHeader( + retryAfterHeader + ); if (delayInMs) { return delay(delayInMs).then((_: any) => this._nextPolicy.sendRequest(httpRequest)); } diff --git a/lib/policies/userAgentPolicy.ts b/lib/policies/userAgentPolicy.ts index eb81760..c4e70db 100644 --- a/lib/policies/userAgentPolicy.ts +++ b/lib/policies/userAgentPolicy.ts @@ -6,24 +6,35 @@ import { HttpOperationResponse } from "../httpOperationResponse"; import { Constants } from "../util/constants"; import { WebResourceLike } from "../webResource"; import { getDefaultUserAgentKey, getPlatformSpecificData } from "./msRestUserAgentPolicy"; -import { BaseRequestPolicy, RequestPolicy, RequestPolicyFactory, RequestPolicyOptionsLike } from "./requestPolicy"; +import { + BaseRequestPolicy, + RequestPolicy, + RequestPolicyFactory, + RequestPolicyOptionsLike, +} from "./requestPolicy"; export type TelemetryInfo = { key?: string; value?: string }; function getRuntimeInfo(): TelemetryInfo[] { const msRestRuntime = { key: "ms-rest-js", - value: Constants.msRestVersion + value: Constants.msRestVersion, }; return [msRestRuntime]; } -function getUserAgentString(telemetryInfo: TelemetryInfo[], keySeparator = " ", valueSeparator = "/"): string { - return telemetryInfo.map(info => { - const value = info.value ? `${valueSeparator}${info.value}` : ""; - return `${info.key}${value}`; - }).join(keySeparator); +function getUserAgentString( + telemetryInfo: TelemetryInfo[], + keySeparator = " ", + valueSeparator = "/" +): string { + return telemetryInfo + .map((info) => { + const value = info.value ? `${valueSeparator}${info.value}` : ""; + return `${info.key}${value}`; + }) + .join(keySeparator); } export const getDefaultUserAgentHeaderName = getDefaultUserAgentKey; @@ -36,18 +47,27 @@ export function getDefaultUserAgentValue(): string { } export function userAgentPolicy(userAgentData?: TelemetryInfo): RequestPolicyFactory { - const key: string = (!userAgentData || userAgentData.key == undefined) ? getDefaultUserAgentKey() : userAgentData.key; - const value: string = (!userAgentData || userAgentData.value == undefined) ? getDefaultUserAgentValue() : userAgentData.value; + const key: string = + !userAgentData || userAgentData.key == undefined ? getDefaultUserAgentKey() : userAgentData.key; + const value: string = + !userAgentData || userAgentData.value == undefined + ? getDefaultUserAgentValue() + : userAgentData.value; return { create: (nextPolicy: RequestPolicy, options: RequestPolicyOptionsLike) => { return new UserAgentPolicy(nextPolicy, options, key, value); - } + }, }; } export class UserAgentPolicy extends BaseRequestPolicy { - constructor(readonly _nextPolicy: RequestPolicy, readonly _options: RequestPolicyOptionsLike, protected headerKey: string, protected headerValue: string) { + constructor( + readonly _nextPolicy: RequestPolicy, + readonly _options: RequestPolicyOptionsLike, + protected headerKey: string, + protected headerValue: string + ) { super(_nextPolicy, _options); } diff --git a/lib/proxyAgent.ts b/lib/proxyAgent.ts index 1b988b6..16c62ce 100644 --- a/lib/proxyAgent.ts +++ b/lib/proxyAgent.ts @@ -10,16 +10,20 @@ import { URLBuilder } from "./url"; import { HttpHeadersLike } from "./httpHeaders"; export type ProxyAgent = { isHttps: boolean; agent: http.Agent | https.Agent }; -export function createProxyAgent(requestUrl: string, proxySettings: ProxySettings, headers?: HttpHeadersLike): ProxyAgent { +export function createProxyAgent( + requestUrl: string, + proxySettings: ProxySettings, + headers?: HttpHeadersLike +): ProxyAgent { const tunnelOptions: tunnel.HttpsOverHttpsOptions = { proxy: { host: URLBuilder.parse(proxySettings.host).getHost() as string, port: proxySettings.port, - headers: (headers && headers.rawHeaders()) || {} - } + headers: (headers && headers.rawHeaders()) || {}, + }, }; - if ((proxySettings.username && proxySettings.password)) { + if (proxySettings.username && proxySettings.password) { tunnelOptions.proxy!.proxyAuth = `${proxySettings.username}:${proxySettings.password}`; } @@ -30,13 +34,17 @@ export function createProxyAgent(requestUrl: string, proxySettings: ProxySetting const proxyAgent = { isHttps: isRequestHttps, - agent: createTunnel(isRequestHttps, isProxyHttps, tunnelOptions) + agent: createTunnel(isRequestHttps, isProxyHttps, tunnelOptions), }; return proxyAgent; } -export function createTunnel(isRequestHttps: boolean, isProxyHttps: boolean, tunnelOptions: tunnel.HttpsOverHttpsOptions): http.Agent | https.Agent { +export function createTunnel( + isRequestHttps: boolean, + isProxyHttps: boolean, + tunnelOptions: tunnel.HttpsOverHttpsOptions +): http.Agent | https.Agent { if (isRequestHttps && isProxyHttps) { return tunnel.httpsOverHttps(tunnelOptions); } else if (isRequestHttps && !isProxyHttps) { diff --git a/lib/restError.ts b/lib/restError.ts index 699fffd..88479c4 100644 --- a/lib/restError.ts +++ b/lib/restError.ts @@ -14,7 +14,14 @@ export class RestError extends Error { request?: WebResourceLike; response?: HttpOperationResponse; body?: any; - constructor(message: string, code?: string, statusCode?: number, request?: WebResourceLike, response?: HttpOperationResponse, body?: any) { + constructor( + message: string, + code?: string, + statusCode?: number, + request?: WebResourceLike, + response?: HttpOperationResponse, + body?: any + ) { super(message); this.code = code; this.statusCode = statusCode; @@ -24,4 +31,4 @@ export class RestError extends Error { Object.setPrototypeOf(this, RestError.prototype); } -} \ No newline at end of file +} diff --git a/lib/serializer.ts b/lib/serializer.ts index 885015f..a78079f 100644 --- a/lib/serializer.ts +++ b/lib/serializer.ts @@ -5,13 +5,18 @@ import * as base64 from "./util/base64"; import * as utils from "./util/utils"; export class Serializer { - constructor(public readonly modelMappers: { [key: string]: any } = {}, public readonly isXML?: boolean) { } + constructor( + public readonly modelMappers: { [key: string]: any } = {}, + public readonly isXML?: boolean + ) {} validateConstraints(mapper: Mapper, value: any, objectName: string): void { const failValidation = (constraintName: keyof MapperConstraints, constraintValue: any) => { - throw new Error(`"${objectName}" with value "${value}" should satisfy the constraint "${constraintName}": ${constraintValue}.`); + throw new Error( + `"${objectName}" with value "${value}" should satisfy the constraint "${constraintName}": ${constraintValue}.` + ); }; - if (mapper.constraints && (value != undefined)) { + if (mapper.constraints && value != undefined) { const { ExclusiveMaximum, ExclusiveMinimum, @@ -23,7 +28,7 @@ export class Serializer { MinLength, MultipleOf, Pattern, - UniqueItems + UniqueItems, } = mapper.constraints; if (ExclusiveMaximum != undefined && value >= ExclusiveMaximum) { failValidation("ExclusiveMaximum", ExclusiveMaximum); @@ -54,11 +59,14 @@ export class Serializer { } if (Pattern) { const pattern: RegExp = typeof Pattern === "string" ? new RegExp(Pattern) : Pattern; - if ((typeof value !== "string") || (value.match(pattern) === null)) { + if (typeof value !== "string" || value.match(pattern) === null) { failValidation("Pattern", Pattern); } } - if (UniqueItems && value.some((item: any, i: number, ar: Array) => ar.indexOf(item) !== i)) { + if ( + UniqueItems && + value.some((item: any, i: number, ar: Array) => ar.indexOf(item) !== i) + ) { failValidation("UniqueItems", UniqueItems); } } @@ -81,7 +89,7 @@ export class Serializer { if (!objectName) { objectName = mapper.serializedName!; } - if (mapperType.match(/^Sequence$/ig) !== null) { + if (mapperType.match(/^Sequence$/gi) !== null) { payload = []; } @@ -116,24 +124,26 @@ export class Serializer { } else { // Validate Constraints if any this.validateConstraints(mapper, object, objectName); - if (mapperType.match(/^any$/ig) !== null) { + if (mapperType.match(/^any$/gi) !== null) { payload = object; - } else if (mapperType.match(/^(Number|String|Boolean|Object|Stream|Uuid)$/ig) !== null) { + } else if (mapperType.match(/^(Number|String|Boolean|Object|Stream|Uuid)$/gi) !== null) { payload = serializeBasicTypes(mapperType, objectName, object); - } else if (mapperType.match(/^Enum$/ig) !== null) { + } else if (mapperType.match(/^Enum$/gi) !== null) { const enumMapper: EnumMapper = mapper as EnumMapper; payload = serializeEnumType(objectName, enumMapper.type.allowedValues, object); - } else if (mapperType.match(/^(Date|DateTime|TimeSpan|DateTimeRfc1123|UnixTime)$/ig) !== null) { + } else if ( + mapperType.match(/^(Date|DateTime|TimeSpan|DateTimeRfc1123|UnixTime)$/gi) !== null + ) { payload = serializeDateTypes(mapperType, object, objectName); - } else if (mapperType.match(/^ByteArray$/ig) !== null) { + } else if (mapperType.match(/^ByteArray$/gi) !== null) { payload = serializeByteArrayType(objectName, object); - } else if (mapperType.match(/^Base64Url$/ig) !== null) { + } else if (mapperType.match(/^Base64Url$/gi) !== null) { payload = serializeBase64UrlType(objectName, object); - } else if (mapperType.match(/^Sequence$/ig) !== null) { + } else if (mapperType.match(/^Sequence$/gi) !== null) { payload = serializeSequenceType(this, mapper as SequenceMapper, object, objectName); - } else if (mapperType.match(/^Dictionary$/ig) !== null) { + } else if (mapperType.match(/^Dictionary$/gi) !== null) { payload = serializeDictionaryType(this, mapper as DictionaryMapper, object, objectName); - } else if (mapperType.match(/^Composite$/ig) !== null) { + } else if (mapperType.match(/^Composite$/gi) !== null) { payload = serializeCompositeType(this, mapper as CompositeMapper, object, objectName); } } @@ -172,7 +182,7 @@ export class Serializer { objectName = mapper.serializedName!; } - if (mapperType.match(/^Composite$/ig) !== null) { + if (mapperType.match(/^Composite$/gi) !== null) { payload = deserializeCompositeType(this, mapper as CompositeMapper, responseBody, objectName); } else { if (this.isXML) { @@ -186,12 +196,12 @@ export class Serializer { } } - if (mapperType.match(/^Number$/ig) !== null) { + if (mapperType.match(/^Number$/gi) !== null) { payload = parseFloat(responseBody); if (isNaN(payload)) { payload = responseBody; } - } else if (mapperType.match(/^Boolean$/ig) !== null) { + } else if (mapperType.match(/^Boolean$/gi) !== null) { if (responseBody === "true") { payload = true; } else if (responseBody === "false") { @@ -199,20 +209,25 @@ export class Serializer { } else { payload = responseBody; } - } else if (mapperType.match(/^(String|Enum|Object|Stream|Uuid|TimeSpan|any)$/ig) !== null) { + } else if (mapperType.match(/^(String|Enum|Object|Stream|Uuid|TimeSpan|any)$/gi) !== null) { payload = responseBody; - } else if (mapperType.match(/^(Date|DateTime|DateTimeRfc1123)$/ig) !== null) { + } else if (mapperType.match(/^(Date|DateTime|DateTimeRfc1123)$/gi) !== null) { payload = new Date(responseBody); - } else if (mapperType.match(/^UnixTime$/ig) !== null) { + } else if (mapperType.match(/^UnixTime$/gi) !== null) { payload = unixTimeToDate(responseBody); - } else if (mapperType.match(/^ByteArray$/ig) !== null) { + } else if (mapperType.match(/^ByteArray$/gi) !== null) { payload = base64.decodeString(responseBody); - } else if (mapperType.match(/^Base64Url$/ig) !== null) { + } else if (mapperType.match(/^Base64Url$/gi) !== null) { payload = base64UrlToByteArray(responseBody); - } else if (mapperType.match(/^Sequence$/ig) !== null) { + } else if (mapperType.match(/^Sequence$/gi) !== null) { payload = deserializeSequenceType(this, mapper as SequenceMapper, responseBody, objectName); - } else if (mapperType.match(/^Dictionary$/ig) !== null) { - payload = deserializeDictionaryType(this, mapper as DictionaryMapper, responseBody, objectName); + } else if (mapperType.match(/^Dictionary$/gi) !== null) { + payload = deserializeDictionaryType( + this, + mapper as DictionaryMapper, + responseBody, + objectName + ); } } @@ -226,7 +241,7 @@ export class Serializer { function trimEnd(str: string, ch: string) { let len = str.length; - while ((len - 1) >= 0 && str[len - 1] === ch) { + while (len - 1 >= 0 && str[len - 1] === ch) { --len; } return str.substr(0, len); @@ -298,30 +313,36 @@ function unixTimeToDate(n: number): Date | undefined { function serializeBasicTypes(typeName: string, objectName: string, value: any): any { if (value !== null && value !== undefined) { - if (typeName.match(/^Number$/ig) !== null) { + if (typeName.match(/^Number$/gi) !== null) { if (typeof value !== "number") { throw new Error(`${objectName} with value ${value} must be of type number.`); } - } else if (typeName.match(/^String$/ig) !== null) { + } else if (typeName.match(/^String$/gi) !== null) { if (typeof value.valueOf() !== "string") { throw new Error(`${objectName} with value "${value}" must be of type string.`); } - } else if (typeName.match(/^Uuid$/ig) !== null) { + } else if (typeName.match(/^Uuid$/gi) !== null) { if (!(typeof value.valueOf() === "string" && utils.isValidUuid(value))) { - throw new Error(`${objectName} with value "${value}" must be of type string and a valid uuid.`); + throw new Error( + `${objectName} with value "${value}" must be of type string and a valid uuid.` + ); } - } else if (typeName.match(/^Boolean$/ig) !== null) { + } else if (typeName.match(/^Boolean$/gi) !== null) { if (typeof value !== "boolean") { throw new Error(`${objectName} with value ${value} must be of type boolean.`); } - } else if (typeName.match(/^Stream$/ig) !== null) { + } else if (typeName.match(/^Stream$/gi) !== null) { const objectType = typeof value; - if (objectType !== "string" && + if ( + objectType !== "string" && objectType !== "function" && !(value instanceof ArrayBuffer) && !ArrayBuffer.isView(value) && - !(typeof Blob === "function" && value instanceof Blob)) { - throw new Error(`${objectName} must be a string, Blob, ArrayBuffer, ArrayBufferView, or a function returning NodeJS.ReadableStream.`); + !(typeof Blob === "function" && value instanceof Blob) + ) { + throw new Error( + `${objectName} must be a string, Blob, ArrayBuffer, ArrayBufferView, or a function returning NodeJS.ReadableStream.` + ); } } } @@ -330,7 +351,9 @@ function serializeBasicTypes(typeName: string, objectName: string, value: any): function serializeEnumType(objectName: string, allowedValues: Array, value: any): any { if (!allowedValues) { - throw new Error(`Please provide a set of allowedValues to validate ${objectName} as an Enum Type.`); + throw new Error( + `Please provide a set of allowedValues to validate ${objectName} as an Enum Type.` + ); } const isPresent = allowedValues.some((item) => { if (typeof item.valueOf() === "string") { @@ -339,7 +362,11 @@ function serializeEnumType(objectName: string, allowedValues: Array, value: return item === value; }); if (!isPresent) { - throw new Error(`${value} is not a valid value for ${objectName}. The valid values are: ${JSON.stringify(allowedValues)}.`); + throw new Error( + `${value} is not a valid value for ${objectName}. The valid values are: ${JSON.stringify( + allowedValues + )}.` + ); } return value; } @@ -366,34 +393,57 @@ function serializeBase64UrlType(objectName: string, value: any): any { function serializeDateTypes(typeName: string, value: any, objectName: string) { if (value != undefined) { - if (typeName.match(/^Date$/ig) !== null) { - if (!(value instanceof Date || - (typeof value.valueOf() === "string" && !isNaN(Date.parse(value))))) { + if (typeName.match(/^Date$/gi) !== null) { + if ( + !( + value instanceof Date || + (typeof value.valueOf() === "string" && !isNaN(Date.parse(value))) + ) + ) { throw new Error(`${objectName} must be an instanceof Date or a string in ISO8601 format.`); } - value = (value instanceof Date) ? value.toISOString().substring(0, 10) : new Date(value).toISOString().substring(0, 10); - } else if (typeName.match(/^DateTime$/ig) !== null) { - if (!(value instanceof Date || - (typeof value.valueOf() === "string" && !isNaN(Date.parse(value))))) { + value = + value instanceof Date + ? value.toISOString().substring(0, 10) + : new Date(value).toISOString().substring(0, 10); + } else if (typeName.match(/^DateTime$/gi) !== null) { + if ( + !( + value instanceof Date || + (typeof value.valueOf() === "string" && !isNaN(Date.parse(value))) + ) + ) { throw new Error(`${objectName} must be an instanceof Date or a string in ISO8601 format.`); } - value = (value instanceof Date) ? value.toISOString() : new Date(value).toISOString(); - } else if (typeName.match(/^DateTimeRfc1123$/ig) !== null) { - if (!(value instanceof Date || - (typeof value.valueOf() === "string" && !isNaN(Date.parse(value))))) { + value = value instanceof Date ? value.toISOString() : new Date(value).toISOString(); + } else if (typeName.match(/^DateTimeRfc1123$/gi) !== null) { + if ( + !( + value instanceof Date || + (typeof value.valueOf() === "string" && !isNaN(Date.parse(value))) + ) + ) { throw new Error(`${objectName} must be an instanceof Date or a string in RFC-1123 format.`); } - value = (value instanceof Date) ? value.toUTCString() : new Date(value).toUTCString(); - } else if (typeName.match(/^UnixTime$/ig) !== null) { - if (!(value instanceof Date || - (typeof value.valueOf() === "string" && !isNaN(Date.parse(value))))) { - throw new Error(`${objectName} must be an instanceof Date or a string in RFC-1123/ISO8601 format ` + - `for it to be serialized in UnixTime/Epoch format.`); + value = value instanceof Date ? value.toUTCString() : new Date(value).toUTCString(); + } else if (typeName.match(/^UnixTime$/gi) !== null) { + if ( + !( + value instanceof Date || + (typeof value.valueOf() === "string" && !isNaN(Date.parse(value))) + ) + ) { + throw new Error( + `${objectName} must be an instanceof Date or a string in RFC-1123/ISO8601 format ` + + `for it to be serialized in UnixTime/Epoch format.` + ); } value = dateToUnixTime(value); - } else if (typeName.match(/^TimeSpan$/ig) !== null) { + } else if (typeName.match(/^TimeSpan$/gi) !== null) { if (!utils.isDuration(value)) { - throw new Error(`${objectName} must be a string in ISO 8601 format. Instead was "${value}".`); + throw new Error( + `${objectName} must be a string in ISO 8601 format. Instead was "${value}".` + ); } value = value; } @@ -401,14 +451,21 @@ function serializeDateTypes(typeName: string, value: any, objectName: string) { return value; } -function serializeSequenceType(serializer: Serializer, mapper: SequenceMapper, object: any, objectName: string) { +function serializeSequenceType( + serializer: Serializer, + mapper: SequenceMapper, + object: any, + objectName: string +) { if (!Array.isArray(object)) { throw new Error(`${objectName} must be of type Array.`); } const elementType = mapper.type.element; if (!elementType || typeof elementType !== "object") { - throw new Error(`element" metadata for an Array must be defined in the ` + - `mapper and it must of type "object" in ${objectName}.`); + throw new Error( + `element" metadata for an Array must be defined in the ` + + `mapper and it must of type "object" in ${objectName}.` + ); } const tempArray = []; for (let i = 0; i < object.length; i++) { @@ -417,14 +474,21 @@ function serializeSequenceType(serializer: Serializer, mapper: SequenceMapper, o return tempArray; } -function serializeDictionaryType(serializer: Serializer, mapper: DictionaryMapper, object: any, objectName: string) { +function serializeDictionaryType( + serializer: Serializer, + mapper: DictionaryMapper, + object: any, + objectName: string +) { if (typeof object !== "object") { throw new Error(`${objectName} must be of type object.`); } const valueType = mapper.type.value; if (!valueType || typeof valueType !== "object") { - throw new Error(`"value" metadata for a Dictionary must be defined in the ` + - `mapper and it must of type "object" in ${objectName}.`); + throw new Error( + `"value" metadata for a Dictionary must be defined in the ` + + `mapper and it must of type "object" in ${objectName}.` + ); } const tempDictionary: { [key: string]: any } = {}; for (const key of Object.keys(object)) { @@ -438,12 +502,22 @@ function serializeDictionaryType(serializer: Serializer, mapper: DictionaryMappe * @param serializer the serializer containing the entire set of mappers * @param mapper the composite mapper to resolve */ -function resolveModelProperties(serializer: Serializer, mapper: CompositeMapper, objectName: string): { [propertyName: string]: Mapper } { +function resolveModelProperties( + serializer: Serializer, + mapper: CompositeMapper, + objectName: string +): { [propertyName: string]: Mapper } { let modelProps = mapper.type.modelProperties; if (!modelProps) { const className = mapper.type.className; if (!className) { - throw new Error(`Class name for model "${objectName}" is not provided in the mapper "${JSON.stringify(mapper, undefined, 2)}".`); + throw new Error( + `Class name for model "${objectName}" is not provided in the mapper "${JSON.stringify( + mapper, + undefined, + 2 + )}".` + ); } const modelMapper = serializer.modelMappers[className]; @@ -452,15 +526,24 @@ function resolveModelProperties(serializer: Serializer, mapper: CompositeMapper, } modelProps = modelMapper.type.modelProperties; if (!modelProps) { - throw new Error(`modelProperties cannot be null or undefined in the ` + - `mapper "${JSON.stringify(modelMapper)}" of type "${className}" for object "${objectName}".`); + throw new Error( + `modelProperties cannot be null or undefined in the ` + + `mapper "${JSON.stringify( + modelMapper + )}" of type "${className}" for object "${objectName}".` + ); } } return modelProps; } -function serializeCompositeType(serializer: Serializer, mapper: CompositeMapper, object: any, objectName: string) { +function serializeCompositeType( + serializer: Serializer, + mapper: CompositeMapper, + object: any, + objectName: string +) { if (getPolymorphicDiscriminatorRecursively(serializer, mapper)) { mapper = getPolymorphicMapper(serializer, mapper, object, "clientName"); } @@ -488,7 +571,7 @@ function serializeCompositeType(serializer: Serializer, mapper: CompositeMapper, for (const pathName of paths) { const childObject = parentObject[pathName]; - if ((childObject == undefined) && (object[key] != undefined)) { + if (childObject == undefined && object[key] != undefined) { parentObject[pathName] = {}; } parentObject = parentObject[pathName]; @@ -496,17 +579,26 @@ function serializeCompositeType(serializer: Serializer, mapper: CompositeMapper, } if (parentObject != undefined) { - const propertyObjectName = propertyMapper.serializedName !== "" - ? objectName + "." + propertyMapper.serializedName - : objectName; + const propertyObjectName = + propertyMapper.serializedName !== "" + ? objectName + "." + propertyMapper.serializedName + : objectName; let toSerialize = object[key]; const polymorphicDiscriminator = getPolymorphicDiscriminatorRecursively(serializer, mapper); - if (polymorphicDiscriminator && polymorphicDiscriminator.clientName === key && toSerialize == undefined) { + if ( + polymorphicDiscriminator && + polymorphicDiscriminator.clientName === key && + toSerialize == undefined + ) { toSerialize = mapper.serializedName; } - const serializedValue = serializer.serialize(propertyMapper, toSerialize, propertyObjectName); + const serializedValue = serializer.serialize( + propertyMapper, + toSerialize, + propertyObjectName + ); if (serializedValue !== undefined && propName != undefined) { if (propertyMapper.xmlIsAttribute) { // $ is the key attributes are kept under in xml2js. @@ -527,9 +619,13 @@ function serializeCompositeType(serializer: Serializer, mapper: CompositeMapper, if (additionalPropertiesMapper) { const propNames = Object.keys(modelProps); for (const clientPropName in object) { - const isAdditionalProperty = propNames.every(pn => pn !== clientPropName); + const isAdditionalProperty = propNames.every((pn) => pn !== clientPropName); if (isAdditionalProperty) { - payload[clientPropName] = serializer.serialize(additionalPropertiesMapper, object[clientPropName], objectName + '["' + clientPropName + '"]'); + payload[clientPropName] = serializer.serialize( + additionalPropertiesMapper, + object[clientPropName], + objectName + '["' + clientPropName + '"]' + ); } } } @@ -543,7 +639,12 @@ function isSpecialXmlProperty(propertyName: string): boolean { return ["$", "_"].includes(propertyName); } -function deserializeCompositeType(serializer: Serializer, mapper: CompositeMapper, responseBody: any, objectName: string): any { +function deserializeCompositeType( + serializer: Serializer, + mapper: CompositeMapper, + responseBody: any, + objectName: string +): any { if (getPolymorphicDiscriminatorRecursively(serializer, mapper)) { mapper = getPolymorphicMapper(serializer, mapper, responseBody, "serializedName"); } @@ -567,7 +668,11 @@ function deserializeCompositeType(serializer: Serializer, mapper: CompositeMappe const dictionary: any = {}; for (const headerKey of Object.keys(responseBody)) { if (headerKey.startsWith(headerCollectionPrefix)) { - dictionary[headerKey.substring(headerCollectionPrefix.length)] = serializer.deserialize((propertyMapper as DictionaryMapper).type.value, responseBody[headerKey], propertyObjectName); + dictionary[headerKey.substring(headerCollectionPrefix.length)] = serializer.deserialize( + (propertyMapper as DictionaryMapper).type.value, + responseBody[headerKey], + propertyObjectName + ); } handledPropertyNames.push(headerKey); @@ -575,7 +680,11 @@ function deserializeCompositeType(serializer: Serializer, mapper: CompositeMappe instance[key] = dictionary; } else if (serializer.isXML) { if (propertyMapper.xmlIsAttribute && responseBody.$) { - instance[key] = serializer.deserialize(propertyMapper, responseBody.$[xmlName!], propertyObjectName); + instance[key] = serializer.deserialize( + propertyMapper, + responseBody.$[xmlName!], + propertyObjectName + ); } else { const propertyName = xmlElementName || xmlName || serializedName; let unwrappedProperty = responseBody[propertyName!]; @@ -588,7 +697,11 @@ function deserializeCompositeType(serializer: Serializer, mapper: CompositeMappe unwrappedProperty = []; } } - instance[key] = serializer.deserialize(propertyMapper, unwrappedProperty, propertyObjectName); + instance[key] = serializer.deserialize( + propertyMapper, + unwrappedProperty, + propertyObjectName + ); } } else { // deserialize the property if it is present in the provided responseBody instance @@ -610,7 +723,11 @@ function deserializeCompositeType(serializer: Serializer, mapper: CompositeMappe // the clientName transformation of the polymorphicDiscriminator (ex: "fishtype") and // the transformation of model property name (ex: "fishtype") is done consistently. // Hence, it is a safer bet to rely on the clientName of the polymorphicDiscriminator. - if (polymorphicDiscriminator && key === polymorphicDiscriminator.clientName && propertyInstance == undefined) { + if ( + polymorphicDiscriminator && + key === polymorphicDiscriminator.clientName && + propertyInstance == undefined + ) { propertyInstance = mapper.serializedName; } @@ -620,7 +737,11 @@ function deserializeCompositeType(serializer: Serializer, mapper: CompositeMappe propertyInstance = responseBody[key]; instance = serializer.deserialize(propertyMapper, propertyInstance, propertyObjectName); } else if (propertyInstance !== undefined || propertyMapper.defaultValue !== undefined) { - serializedValue = serializer.deserialize(propertyMapper, propertyInstance, propertyObjectName); + serializedValue = serializer.deserialize( + propertyMapper, + propertyInstance, + propertyObjectName + ); instance[key] = serializedValue; } } @@ -640,12 +761,20 @@ function deserializeCompositeType(serializer: Serializer, mapper: CompositeMappe for (const responsePropName in responseBody) { if (isAdditionalProperty(responsePropName)) { - instance[responsePropName] = serializer.deserialize(additionalPropertiesMapper, responseBody[responsePropName], objectName + '["' + responsePropName + '"]'); + instance[responsePropName] = serializer.deserialize( + additionalPropertiesMapper, + responseBody[responsePropName], + objectName + '["' + responsePropName + '"]' + ); } } } else if (responseBody) { for (const key of Object.keys(responseBody)) { - if (instance[key] === undefined && !handledPropertyNames.includes(key) && !isSpecialXmlProperty(key)) { + if ( + instance[key] === undefined && + !handledPropertyNames.includes(key) && + !isSpecialXmlProperty(key) + ) { instance[key] = responseBody[key]; } } @@ -654,12 +783,19 @@ function deserializeCompositeType(serializer: Serializer, mapper: CompositeMappe return instance; } -function deserializeDictionaryType(serializer: Serializer, mapper: DictionaryMapper, responseBody: any, objectName: string): any { +function deserializeDictionaryType( + serializer: Serializer, + mapper: DictionaryMapper, + responseBody: any, + objectName: string +): any { /*jshint validthis: true */ const value = mapper.type.value; if (!value || typeof value !== "object") { - throw new Error(`"value" metadata for a Dictionary must be defined in the ` + - `mapper and it must of type "object" in ${objectName}`); + throw new Error( + `"value" metadata for a Dictionary must be defined in the ` + + `mapper and it must of type "object" in ${objectName}` + ); } if (responseBody) { const tempDictionary: { [key: string]: any } = {}; @@ -671,12 +807,19 @@ function deserializeDictionaryType(serializer: Serializer, mapper: DictionaryMap return responseBody; } -function deserializeSequenceType(serializer: Serializer, mapper: SequenceMapper, responseBody: any, objectName: string): any { +function deserializeSequenceType( + serializer: Serializer, + mapper: SequenceMapper, + responseBody: any, + objectName: string +): any { /*jshint validthis: true */ const element = mapper.type.element; if (!element || typeof element !== "object") { - throw new Error(`element" metadata for an Array must be defined in the ` + - `mapper and it must of type "object" in ${objectName}`); + throw new Error( + `element" metadata for an Array must be defined in the ` + + `mapper and it must of type "object" in ${objectName}` + ); } if (responseBody) { if (!Array.isArray(responseBody)) { @@ -693,7 +836,12 @@ function deserializeSequenceType(serializer: Serializer, mapper: SequenceMapper, return responseBody; } -function getPolymorphicMapper(serializer: Serializer, mapper: CompositeMapper, object: any, polymorphicPropertyName: "clientName" | "serializedName"): CompositeMapper { +function getPolymorphicMapper( + serializer: Serializer, + mapper: CompositeMapper, + object: any, + polymorphicPropertyName: "clientName" | "serializedName" +): CompositeMapper { const polymorphicDiscriminator = getPolymorphicDiscriminatorRecursively(serializer, mapper); if (polymorphicDiscriminator) { const discriminatorName = polymorphicDiscriminator[polymorphicPropertyName]; @@ -701,9 +849,10 @@ function getPolymorphicMapper(serializer: Serializer, mapper: CompositeMapper, o const discriminatorValue = object[discriminatorName]; if (discriminatorValue != undefined) { const typeName = mapper.type.uberParent || mapper.type.className; - const indexDiscriminator = discriminatorValue === typeName - ? discriminatorValue - : typeName + "." + discriminatorValue; + const indexDiscriminator = + discriminatorValue === typeName + ? discriminatorValue + : typeName + "." + discriminatorValue; const polymorphicMapper = serializer.modelMappers.discriminators[indexDiscriminator]; if (polymorphicMapper) { mapper = polymorphicMapper; @@ -714,14 +863,23 @@ function getPolymorphicMapper(serializer: Serializer, mapper: CompositeMapper, o return mapper; } -function getPolymorphicDiscriminatorRecursively(serializer: Serializer, mapper: CompositeMapper): PolymorphicDiscriminator | undefined { - return mapper.type.polymorphicDiscriminator - || getPolymorphicDiscriminatorSafely(serializer, mapper.type.uberParent) - || getPolymorphicDiscriminatorSafely(serializer, mapper.type.className); +function getPolymorphicDiscriminatorRecursively( + serializer: Serializer, + mapper: CompositeMapper +): PolymorphicDiscriminator | undefined { + return ( + mapper.type.polymorphicDiscriminator || + getPolymorphicDiscriminatorSafely(serializer, mapper.type.uberParent) || + getPolymorphicDiscriminatorSafely(serializer, mapper.type.className) + ); } function getPolymorphicDiscriminatorSafely(serializer: Serializer, typeName?: string) { - return (typeName && serializer.modelMappers[typeName] && serializer.modelMappers[typeName].type.polymorphicDiscriminator); + return ( + typeName && + serializer.modelMappers[typeName] && + serializer.modelMappers[typeName].type.polymorphicDiscriminator + ); } export interface MapperConstraints { @@ -738,23 +896,29 @@ export interface MapperConstraints { MultipleOf?: number; } -export type MapperType = SimpleMapperType | CompositeMapperType | SequenceMapperType | DictionaryMapperType | EnumMapperType; +export type MapperType = + | SimpleMapperType + | CompositeMapperType + | SequenceMapperType + | DictionaryMapperType + | EnumMapperType; export interface SimpleMapperType { - name: "Base64Url" - | "Boolean" - | "ByteArray" - | "Date" - | "DateTime" - | "DateTimeRfc1123" - | "Object" - | "Stream" - | "String" - | "TimeSpan" - | "UnixTime" - | "Uuid" - | "Number" - | "any"; + name: + | "Base64Url" + | "Boolean" + | "ByteArray" + | "Date" + | "DateTime" + | "DateTimeRfc1123" + | "Object" + | "Stream" + | "String" + | "TimeSpan" + | "UnixTime" + | "Uuid" + | "Number" + | "any"; } export interface CompositeMapperType { @@ -838,11 +1002,9 @@ export function serializeObject(toSerialize: any): any { if (toSerialize instanceof Uint8Array) { toSerialize = base64.encodeByteArray(toSerialize); return toSerialize; - } - else if (toSerialize instanceof Date) { + } else if (toSerialize instanceof Date) { return toSerialize.toISOString(); - } - else if (Array.isArray(toSerialize)) { + } else if (Array.isArray(toSerialize)) { const array = []; for (let i = 0; i < toSerialize.length; i++) { array.push(serializeObject(toSerialize[i])); @@ -885,5 +1047,5 @@ export const MapperType = strEnum([ "String", "Stream", "TimeSpan", - "UnixTime" + "UnixTime", ]); diff --git a/lib/serviceClient.ts b/lib/serviceClient.ts index 8bc796b..9ff8b0a 100644 --- a/lib/serviceClient.ts +++ b/lib/serviceClient.ts @@ -8,14 +8,31 @@ import { HttpClient } from "./httpClient"; import { HttpOperationResponse, RestResponse } from "./httpOperationResponse"; import { HttpPipelineLogger } from "./httpPipelineLogger"; import { OperationArguments } from "./operationArguments"; -import { getPathStringFromParameter, getPathStringFromParameterPath, OperationParameter, ParameterPath } from "./operationParameter"; +import { + getPathStringFromParameter, + getPathStringFromParameterPath, + OperationParameter, + ParameterPath, +} from "./operationParameter"; import { isStreamOperation, OperationSpec } from "./operationSpec"; -import { deserializationPolicy, DeserializationContentTypes } from "./policies/deserializationPolicy"; +import { + deserializationPolicy, + DeserializationContentTypes, +} from "./policies/deserializationPolicy"; import { exponentialRetryPolicy } from "./policies/exponentialRetryPolicy"; import { generateClientRequestIdPolicy } from "./policies/generateClientRequestIdPolicy"; -import { userAgentPolicy, getDefaultUserAgentHeaderName, getDefaultUserAgentValue } from "./policies/userAgentPolicy"; +import { + userAgentPolicy, + getDefaultUserAgentHeaderName, + getDefaultUserAgentValue, +} from "./policies/userAgentPolicy"; import { redirectPolicy } from "./policies/redirectPolicy"; -import { RequestPolicy, RequestPolicyFactory, RequestPolicyOptions, RequestPolicyOptionsLike } from "./policies/requestPolicy"; +import { + RequestPolicy, + RequestPolicyFactory, + RequestPolicyOptions, + RequestPolicyOptionsLike, +} from "./policies/requestPolicy"; import { rpRegistrationPolicy } from "./policies/rpRegistrationPolicy"; import { signingPolicy } from "./policies/signingPolicy"; import { systemErrorRetryPolicy } from "./policies/systemErrorRetryPolicy"; @@ -24,7 +41,13 @@ import { CompositeMapper, DictionaryMapper, Mapper, MapperType, Serializer } fro import { URLBuilder } from "./url"; import * as utils from "./util/utils"; import { stringifyXML } from "./util/xml"; -import { RequestOptionsBase, RequestPrepareOptions, WebResourceLike, isWebResourceLike, WebResource } from "./webResource"; +import { + RequestOptionsBase, + RequestPrepareOptions, + WebResourceLike, + isWebResourceLike, + WebResource, +} from "./webResource"; import { OperationResponse } from "./operationResponse"; import { ServiceCallback } from "./util/utils"; import { agentPolicy } from "./policies/agentPolicy"; @@ -33,7 +56,6 @@ import { throttlingRetryPolicy } from "./policies/throttlingRetryPolicy"; import { Agent } from "http"; import { AzureIdentityCredentialAdapter } from "./credentials/azureIdentityTokenCredentialAdapter"; - /** * HTTP proxy settings (Node.js only) */ @@ -61,7 +83,9 @@ export interface ServiceClientOptions { * request on the wire, or a function that takes in the defaultRequestPolicyFactories and returns * the requestPolicyFactories that will be used. */ - requestPolicyFactories?: RequestPolicyFactory[] | ((defaultRequestPolicyFactories: RequestPolicyFactory[]) => (void | RequestPolicyFactory[])); + requestPolicyFactories?: + | RequestPolicyFactory[] + | ((defaultRequestPolicyFactories: RequestPolicyFactory[]) => void | RequestPolicyFactory[]); /** * The HttpClient that will be used to send HTTP requests. */ @@ -134,7 +158,6 @@ export class ServiceClient { */ protected requestContentType?: string; - /** * The HTTP client that will be used to send requests. */ @@ -150,7 +173,10 @@ export class ServiceClient { * @param {ServiceClientCredentials} [credentials] The credentials object used for authentication. * @param {ServiceClientOptions} [options] The service client options that govern the behavior of the client. */ - constructor(credentials?: ServiceClientCredentials | TokenCredential, options?: ServiceClientOptions) { + constructor( + credentials?: ServiceClientCredentials | TokenCredential, + options?: ServiceClientOptions + ) { if (!options) { options = {}; } @@ -162,7 +188,6 @@ export class ServiceClient { serviceClientCredentials = credentials; } - if (serviceClientCredentials && !serviceClientCredentials.signRequest) { throw new Error("credentials argument needs to implement signRequest method"); } @@ -175,9 +200,14 @@ export class ServiceClient { if (Array.isArray(options.requestPolicyFactories)) { requestPolicyFactories = options.requestPolicyFactories; } else { - requestPolicyFactories = createDefaultRequestPolicyFactories(serviceClientCredentials, options); + requestPolicyFactories = createDefaultRequestPolicyFactories( + serviceClientCredentials, + options + ); if (options.requestPolicyFactories) { - const newRequestPolicyFactories: void | RequestPolicyFactory[] = options.requestPolicyFactories(requestPolicyFactories); + const newRequestPolicyFactories: + | void + | RequestPolicyFactory[] = options.requestPolicyFactories(requestPolicyFactories); if (newRequestPolicyFactories) { requestPolicyFactories = newRequestPolicyFactories; } @@ -210,7 +240,10 @@ export class ServiceClient { let httpPipeline: RequestPolicy = this._httpClient; if (this._requestPolicyFactories && this._requestPolicyFactories.length > 0) { for (let i = this._requestPolicyFactories.length - 1; i >= 0; --i) { - httpPipeline = this._requestPolicyFactories[i].create(httpPipeline, this._requestPolicyOptions); + httpPipeline = this._requestPolicyFactories[i].create( + httpPipeline, + this._requestPolicyOptions + ); } } return httpPipeline.sendRequest(httpRequest); @@ -222,7 +255,11 @@ export class ServiceClient { * @param {OperationSpec} operationSpec The OperationSpec to use to populate the httpRequest. * @param {ServiceCallback} callback The callback to call when the response is received. */ - sendOperationRequest(operationArguments: OperationArguments, operationSpec: OperationSpec, callback?: ServiceCallback): Promise { + sendOperationRequest( + operationArguments: OperationArguments, + operationSpec: OperationSpec, + callback?: ServiceCallback + ): Promise { if (typeof operationArguments.options === "function") { callback = operationArguments.options; operationArguments.options = undefined; @@ -234,7 +271,9 @@ export class ServiceClient { try { const baseUri: string | undefined = operationSpec.baseUrl || this.baseUri; if (!baseUri) { - throw new Error("If operationSpec.baseUrl is not specified, then the ServiceClient must have a baseUri string property that contains the base URL to use."); + throw new Error( + "If operationSpec.baseUrl is not specified, then the ServiceClient must have a baseUri string property that contains the base URL to use." + ); } httpRequest.method = operationSpec.httpMethod; @@ -246,19 +285,40 @@ export class ServiceClient { } if (operationSpec.urlParameters && operationSpec.urlParameters.length > 0) { for (const urlParameter of operationSpec.urlParameters) { - let urlParameterValue: string = getOperationArgumentValueFromParameter(this, operationArguments, urlParameter, operationSpec.serializer); - urlParameterValue = operationSpec.serializer.serialize(urlParameter.mapper, urlParameterValue, getPathStringFromParameter(urlParameter)); + let urlParameterValue: string = getOperationArgumentValueFromParameter( + this, + operationArguments, + urlParameter, + operationSpec.serializer + ); + urlParameterValue = operationSpec.serializer.serialize( + urlParameter.mapper, + urlParameterValue, + getPathStringFromParameter(urlParameter) + ); if (!urlParameter.skipEncoding) { urlParameterValue = encodeURIComponent(urlParameterValue); } - requestUrl.replaceAll(`{${urlParameter.mapper.serializedName || getPathStringFromParameter(urlParameter)}}`, urlParameterValue); + requestUrl.replaceAll( + `{${urlParameter.mapper.serializedName || getPathStringFromParameter(urlParameter)}}`, + urlParameterValue + ); } } if (operationSpec.queryParameters && operationSpec.queryParameters.length > 0) { for (const queryParameter of operationSpec.queryParameters) { - let queryParameterValue: any = getOperationArgumentValueFromParameter(this, operationArguments, queryParameter, operationSpec.serializer); + let queryParameterValue: any = getOperationArgumentValueFromParameter( + this, + operationArguments, + queryParameter, + operationSpec.serializer + ); if (queryParameterValue != undefined) { - queryParameterValue = operationSpec.serializer.serialize(queryParameter.mapper, queryParameterValue, getPathStringFromParameter(queryParameter)); + queryParameterValue = operationSpec.serializer.serialize( + queryParameter.mapper, + queryParameterValue, + getPathStringFromParameter(queryParameter) + ); if (queryParameter.collectionFormat != undefined) { if (queryParameter.collectionFormat === QueryCollectionFormat.Multi) { if (queryParameterValue.length === 0) { @@ -269,26 +329,39 @@ export class ServiceClient { queryParameterValue[index] = item == undefined ? "" : item.toString(); } } - } else if (queryParameter.collectionFormat === QueryCollectionFormat.Ssv || queryParameter.collectionFormat === QueryCollectionFormat.Tsv) { + } else if ( + queryParameter.collectionFormat === QueryCollectionFormat.Ssv || + queryParameter.collectionFormat === QueryCollectionFormat.Tsv + ) { queryParameterValue = queryParameterValue.join(queryParameter.collectionFormat); } } if (!queryParameter.skipEncoding) { if (Array.isArray(queryParameterValue)) { for (const index in queryParameterValue) { - if (queryParameterValue[index] !== undefined && queryParameterValue[index] !== null) { + if ( + queryParameterValue[index] !== undefined && + queryParameterValue[index] !== null + ) { queryParameterValue[index] = encodeURIComponent(queryParameterValue[index]); } } - } - else { + } else { queryParameterValue = encodeURIComponent(queryParameterValue); } } - if (queryParameter.collectionFormat != undefined && queryParameter.collectionFormat !== QueryCollectionFormat.Multi && queryParameter.collectionFormat !== QueryCollectionFormat.Ssv && queryParameter.collectionFormat !== QueryCollectionFormat.Tsv) { + if ( + queryParameter.collectionFormat != undefined && + queryParameter.collectionFormat !== QueryCollectionFormat.Multi && + queryParameter.collectionFormat !== QueryCollectionFormat.Ssv && + queryParameter.collectionFormat !== QueryCollectionFormat.Tsv + ) { queryParameterValue = queryParameterValue.join(queryParameter.collectionFormat); } - requestUrl.setQueryParameter(queryParameter.mapper.serializedName || getPathStringFromParameter(queryParameter), queryParameterValue); + requestUrl.setQueryParameter( + queryParameter.mapper.serializedName || getPathStringFromParameter(queryParameter), + queryParameterValue + ); } } } @@ -301,16 +374,30 @@ export class ServiceClient { if (operationSpec.headerParameters) { for (const headerParameter of operationSpec.headerParameters) { - let headerValue: any = getOperationArgumentValueFromParameter(this, operationArguments, headerParameter, operationSpec.serializer); + let headerValue: any = getOperationArgumentValueFromParameter( + this, + operationArguments, + headerParameter, + operationSpec.serializer + ); if (headerValue != undefined) { - headerValue = operationSpec.serializer.serialize(headerParameter.mapper, headerValue, getPathStringFromParameter(headerParameter)); - const headerCollectionPrefix = (headerParameter.mapper as DictionaryMapper).headerCollectionPrefix; + headerValue = operationSpec.serializer.serialize( + headerParameter.mapper, + headerValue, + getPathStringFromParameter(headerParameter) + ); + const headerCollectionPrefix = (headerParameter.mapper as DictionaryMapper) + .headerCollectionPrefix; if (headerCollectionPrefix) { for (const key of Object.keys(headerValue)) { httpRequest.headers.set(headerCollectionPrefix + key, headerValue[key]); } } else { - httpRequest.headers.set(headerParameter.mapper.serializedName || getPathStringFromParameter(headerParameter), headerValue); + httpRequest.headers.set( + headerParameter.mapper.serializedName || + getPathStringFromParameter(headerParameter), + headerValue + ); } } } @@ -349,8 +436,9 @@ export class ServiceClient { httpRequest.streamResponseBody = isStreamOperation(operationSpec); } - result = this.sendRequest(httpRequest) - .then(res => flattenResponse(res, operationSpec.responses[res.status])); + result = this.sendRequest(httpRequest).then((res) => + flattenResponse(res, operationSpec.responses[res.status]) + ); } catch (error) { result = Promise.reject(error); } @@ -359,47 +447,86 @@ export class ServiceClient { if (cb) { result // tslint:disable-next-line:no-null-keyword - .then(res => cb(null, res._response.parsedBody, res._response.request, res._response)) - .catch(err => cb(err)); + .then((res) => cb(null, res._response.parsedBody, res._response.request, res._response)) + .catch((err) => cb(err)); } return result; } } -export function serializeRequestBody(serviceClient: ServiceClient, httpRequest: WebResourceLike, operationArguments: OperationArguments, operationSpec: OperationSpec): void { +export function serializeRequestBody( + serviceClient: ServiceClient, + httpRequest: WebResourceLike, + operationArguments: OperationArguments, + operationSpec: OperationSpec +): void { if (operationSpec.requestBody && operationSpec.requestBody.mapper) { - httpRequest.body = getOperationArgumentValueFromParameter(serviceClient, operationArguments, operationSpec.requestBody, operationSpec.serializer); + httpRequest.body = getOperationArgumentValueFromParameter( + serviceClient, + operationArguments, + operationSpec.requestBody, + operationSpec.serializer + ); const bodyMapper = operationSpec.requestBody.mapper; const { required, xmlName, xmlElementName, serializedName } = bodyMapper; const typeName = bodyMapper.type.name; try { if (httpRequest.body != undefined || required) { - const requestBodyParameterPathString: string = getPathStringFromParameter(operationSpec.requestBody); - httpRequest.body = operationSpec.serializer.serialize(bodyMapper, httpRequest.body, requestBodyParameterPathString); + const requestBodyParameterPathString: string = getPathStringFromParameter( + operationSpec.requestBody + ); + httpRequest.body = operationSpec.serializer.serialize( + bodyMapper, + httpRequest.body, + requestBodyParameterPathString + ); const isStream = typeName === MapperType.Stream; if (operationSpec.isXML) { if (typeName === MapperType.Sequence) { - httpRequest.body = stringifyXML(utils.prepareXMLRootList(httpRequest.body, xmlElementName || xmlName || serializedName!), { rootName: xmlName || serializedName }); - } - else if (!isStream) { - httpRequest.body = stringifyXML(httpRequest.body, { rootName: xmlName || serializedName }); + httpRequest.body = stringifyXML( + utils.prepareXMLRootList( + httpRequest.body, + xmlElementName || xmlName || serializedName! + ), + { rootName: xmlName || serializedName } + ); + } else if (!isStream) { + httpRequest.body = stringifyXML(httpRequest.body, { + rootName: xmlName || serializedName, + }); } } else if (!isStream) { httpRequest.body = JSON.stringify(httpRequest.body); } } } catch (error) { - throw new Error(`Error "${error.message}" occurred in serializing the payload - ${JSON.stringify(serializedName, undefined, " ")}.`); + throw new Error( + `Error "${error.message}" occurred in serializing the payload - ${JSON.stringify( + serializedName, + undefined, + " " + )}.` + ); } } else if (operationSpec.formDataParameters && operationSpec.formDataParameters.length > 0) { httpRequest.formData = {}; for (const formDataParameter of operationSpec.formDataParameters) { - const formDataParameterValue: any = getOperationArgumentValueFromParameter(serviceClient, operationArguments, formDataParameter, operationSpec.serializer); + const formDataParameterValue: any = getOperationArgumentValueFromParameter( + serviceClient, + operationArguments, + formDataParameter, + operationSpec.serializer + ); if (formDataParameterValue != undefined) { - const formDataParameterPropertyName: string = formDataParameter.mapper.serializedName || getPathStringFromParameter(formDataParameter); - httpRequest.formData[formDataParameterPropertyName] = operationSpec.serializer.serialize(formDataParameter.mapper, formDataParameterValue, getPathStringFromParameter(formDataParameter)); + const formDataParameterPropertyName: string = + formDataParameter.mapper.serializedName || getPathStringFromParameter(formDataParameter); + httpRequest.formData[formDataParameterPropertyName] = operationSpec.serializer.serialize( + formDataParameter.mapper, + formDataParameterValue, + getPathStringFromParameter(formDataParameter) + ); } } } @@ -409,7 +536,10 @@ function isRequestPolicyFactory(instance: any): instance is RequestPolicyFactory return typeof instance.create === "function"; } -function getValueOrFunctionResult(value: undefined | string | ((defaultValue: string) => string), defaultValueCreator: (() => string)): string { +function getValueOrFunctionResult( + value: undefined | string | ((defaultValue: string) => string), + defaultValueCreator: () => string +): string { let result: string; if (typeof value === "string") { result = value; @@ -422,7 +552,10 @@ function getValueOrFunctionResult(value: undefined | string | ((defaultValue: st return result; } -function createDefaultRequestPolicyFactories(credentials: ServiceClientCredentials | RequestPolicyFactory | undefined, options: ServiceClientOptions): RequestPolicyFactory[] { +function createDefaultRequestPolicyFactories( + credentials: ServiceClientCredentials | RequestPolicyFactory | undefined, + options: ServiceClientOptions +): RequestPolicyFactory[] { const factories: RequestPolicyFactory[] = []; if (options.generateClientRequestIdHeader) { @@ -437,8 +570,14 @@ function createDefaultRequestPolicyFactories(credentials: ServiceClientCredentia } } - const userAgentHeaderName: string = getValueOrFunctionResult(options.userAgentHeaderName, getDefaultUserAgentHeaderName); - const userAgentHeaderValue: string = getValueOrFunctionResult(options.userAgent, getDefaultUserAgentValue); + const userAgentHeaderName: string = getValueOrFunctionResult( + options.userAgentHeaderName, + getDefaultUserAgentHeaderName + ); + const userAgentHeaderValue: string = getValueOrFunctionResult( + options.userAgent, + getDefaultUserAgentValue + ); if (userAgentHeaderName && userAgentHeaderValue) { factories.push(userAgentPolicy({ key: userAgentHeaderName, value: userAgentHeaderValue })); } @@ -485,11 +624,28 @@ export function getPropertyParent(parent: PropertyParent, propertyPath: string[] return parent; } -function getOperationArgumentValueFromParameter(serviceClient: ServiceClient, operationArguments: OperationArguments, parameter: OperationParameter, serializer: Serializer): any { - return getOperationArgumentValueFromParameterPath(serviceClient, operationArguments, parameter.parameterPath, parameter.mapper, serializer); +function getOperationArgumentValueFromParameter( + serviceClient: ServiceClient, + operationArguments: OperationArguments, + parameter: OperationParameter, + serializer: Serializer +): any { + return getOperationArgumentValueFromParameterPath( + serviceClient, + operationArguments, + parameter.parameterPath, + parameter.mapper, + serializer + ); } -export function getOperationArgumentValueFromParameterPath(serviceClient: ServiceClient, operationArguments: OperationArguments, parameterPath: ParameterPath, parameterMapper: Mapper, serializer: Serializer): any { +export function getOperationArgumentValueFromParameterPath( + serviceClient: ServiceClient, + operationArguments: OperationArguments, + parameterPath: ParameterPath, + parameterMapper: Mapper, + serializer: Serializer +): any { let value: any; if (typeof parameterPath === "string") { parameterPath = [parameterPath]; @@ -499,20 +655,28 @@ export function getOperationArgumentValueFromParameterPath(serviceClient: Servic if (parameterMapper.isConstant) { value = parameterMapper.defaultValue; } else { - let propertySearchResult: PropertySearchResult = getPropertyFromParameterPath(operationArguments, parameterPath); + let propertySearchResult: PropertySearchResult = getPropertyFromParameterPath( + operationArguments, + parameterPath + ); if (!propertySearchResult.propertyFound) { propertySearchResult = getPropertyFromParameterPath(serviceClient, parameterPath); } let useDefaultValue = false; if (!propertySearchResult.propertyFound) { - useDefaultValue = parameterMapper.required || (parameterPath[0] === "options" && parameterPath.length === 2); + useDefaultValue = + parameterMapper.required || + (parameterPath[0] === "options" && parameterPath.length === 2); } value = useDefaultValue ? parameterMapper.defaultValue : propertySearchResult.propertyValue; } // Serialize just for validation purposes. - const parameterPathString: string = getPathStringFromParameterPath(parameterPath, parameterMapper); + const parameterPathString: string = getPathStringFromParameterPath( + parameterPath, + parameterMapper + ); serializer.serialize(parameterMapper, value, parameterPathString); } } else { @@ -521,11 +685,22 @@ export function getOperationArgumentValueFromParameterPath(serviceClient: Servic } for (const propertyName in parameterPath) { - const propertyMapper: Mapper = (parameterMapper as CompositeMapper).type.modelProperties![propertyName]; + const propertyMapper: Mapper = (parameterMapper as CompositeMapper).type.modelProperties![ + propertyName + ]; const propertyPath: ParameterPath = parameterPath[propertyName]; - const propertyValue: any = getOperationArgumentValueFromParameterPath(serviceClient, operationArguments, propertyPath, propertyMapper, serializer); + const propertyValue: any = getOperationArgumentValueFromParameterPath( + serviceClient, + operationArguments, + propertyPath, + propertyMapper, + serializer + ); // Serialize just for validation purposes. - const propertyPathString: string = getPathStringFromParameterPath(propertyPath, propertyMapper); + const propertyPathString: string = getPathStringFromParameterPath( + propertyPath, + propertyMapper + ); serializer.serialize(propertyMapper, propertyValue, propertyPathString); if (propertyValue !== undefined) { if (!value) { @@ -543,7 +718,10 @@ interface PropertySearchResult { propertyFound: boolean; } -function getPropertyFromParameterPath(parent: { [parameterName: string]: any }, parameterPath: string[]): PropertySearchResult { +function getPropertyFromParameterPath( + parent: { [parameterName: string]: any }, + parameterPath: string[] +): PropertySearchResult { const result: PropertySearchResult = { propertyFound: false }; let i = 0; for (; i < parameterPath.length; ++i) { @@ -562,13 +740,16 @@ function getPropertyFromParameterPath(parent: { [parameterName: string]: any }, return result; } -export function flattenResponse(_response: HttpOperationResponse, responseSpec: OperationResponse | undefined): RestResponse { +export function flattenResponse( + _response: HttpOperationResponse, + responseSpec: OperationResponse | undefined +): RestResponse { const parsedHeaders = _response.parsedHeaders; const bodyMapper = responseSpec && responseSpec.bodyMapper; const addOperationResponse = (obj: {}) => Object.defineProperty(obj, "_response", { - value: _response + value: _response, }); if (bodyMapper) { @@ -577,19 +758,19 @@ export function flattenResponse(_response: HttpOperationResponse, responseSpec: return addOperationResponse({ ...parsedHeaders, blobBody: _response.blobBody, - readableStreamBody: _response.readableStreamBody + readableStreamBody: _response.readableStreamBody, }); } - const modelProperties = typeName === "Composite" && (bodyMapper as CompositeMapper).type.modelProperties || {}; - const isPageableResponse = Object.keys(modelProperties).some(k => modelProperties[k].serializedName === ""); + const modelProperties = + (typeName === "Composite" && (bodyMapper as CompositeMapper).type.modelProperties) || {}; + const isPageableResponse = Object.keys(modelProperties).some( + (k) => modelProperties[k].serializedName === "" + ); if (typeName === "Sequence" || isPageableResponse) { // We're expecting a sequece(array) make sure that the response body is in the // correct format, if not make it an empty array [] - const parsedBody = - Array.isArray(_response.parsedBody) - ? _response.parsedBody - : []; + const parsedBody = Array.isArray(_response.parsedBody) ? _response.parsedBody : []; const arrayResponse = [...parsedBody] as RestResponse & any[]; for (const key of Object.keys(modelProperties)) { @@ -610,21 +791,25 @@ export function flattenResponse(_response: HttpOperationResponse, responseSpec: if (typeName === "Composite" || typeName === "Dictionary") { return addOperationResponse({ ...parsedHeaders, - ..._response.parsedBody + ..._response.parsedBody, }); } } - if (bodyMapper || _response.request.method === "HEAD" || utils.isPrimitiveType(_response.parsedBody)) { + if ( + bodyMapper || + _response.request.method === "HEAD" || + utils.isPrimitiveType(_response.parsedBody) + ) { // primitive body types and HEAD booleans return addOperationResponse({ ...parsedHeaders, - body: _response.parsedBody + body: _response.parsedBody, }); } return addOperationResponse({ ...parsedHeaders, - ..._response.parsedBody + ..._response.parsedBody, }); } diff --git a/lib/url.ts b/lib/url.ts index b14b3ab..ac5e28f 100644 --- a/lib/url.ts +++ b/lib/url.ts @@ -83,40 +83,40 @@ export class URLQuery { for (let i = 0; i < text.length; ++i) { const currentCharacter: string = text[i]; switch (currentState) { - case "ParameterName": - switch (currentCharacter) { - case "=": - currentState = "ParameterValue"; + case "ParameterName": + switch (currentCharacter) { + case "=": + currentState = "ParameterValue"; + break; + + case "&": + parameterName = ""; + parameterValue = ""; + break; + + default: + parameterName += currentCharacter; + break; + } break; - case "&": - parameterName = ""; - parameterValue = ""; + case "ParameterValue": + switch (currentCharacter) { + case "&": + result.set(parameterName, parameterValue); + parameterName = ""; + parameterValue = ""; + currentState = "ParameterName"; + break; + + default: + parameterValue += currentCharacter; + break; + } break; default: - parameterName += currentCharacter; - break; - } - break; - - case "ParameterValue": - switch (currentCharacter) { - case "&": - result.set(parameterName, parameterValue); - parameterName = ""; - parameterValue = ""; - currentState = "ParameterName"; - break; - - default: - parameterValue += currentCharacter; - break; - } - break; - - default: - throw new Error("Unrecognized URLQuery parse state: " + currentState); + throw new Error("Unrecognized URLQuery parse state: " + currentState); } } if (currentState === "ParameterValue") { @@ -290,31 +290,31 @@ export class URLBuilder { const token: URLToken | undefined = tokenizer.current(); if (token) { switch (token.type) { - case "SCHEME": - this._scheme = token.text || undefined; - break; + case "SCHEME": + this._scheme = token.text || undefined; + break; - case "HOST": - this._host = token.text || undefined; - break; + case "HOST": + this._host = token.text || undefined; + break; - case "PORT": - this._port = token.text || undefined; - break; + case "PORT": + this._port = token.text || undefined; + break; - case "PATH": - const tokenPath: string | undefined = token.text || undefined; - if (!this._path || this._path === "/" || tokenPath !== "/") { - this._path = tokenPath; - } - break; + case "PATH": + const tokenPath: string | undefined = token.text || undefined; + if (!this._path || this._path === "/" || tokenPath !== "/") { + this._path = tokenPath; + } + break; - case "QUERY": - this._query = URLQuery.parse(token.text); - break; + case "QUERY": + this._query = URLQuery.parse(token.text); + break; - default: - throw new Error(`Unrecognized URLTokenType: ${token.type}`); + default: + throw new Error(`Unrecognized URLTokenType: ${token.type}`); } } } @@ -375,8 +375,7 @@ type URLTokenizerState = "SCHEME" | "SCHEME_OR_HOST" | "HOST" | "PORT" | "PATH" type URLTokenType = "SCHEME" | "HOST" | "PORT" | "PATH" | "QUERY"; export class URLToken { - public constructor(public readonly text: string, public readonly type: URLTokenType) { - } + public constructor(public readonly text: string, public readonly type: URLTokenType) {} public static scheme(text: string): URLToken { return new URLToken(text, "SCHEME"); @@ -405,9 +404,11 @@ export class URLToken { */ export function isAlphaNumericCharacter(character: string): boolean { const characterCode: number = character.charCodeAt(0); - return (48 /* '0' */ <= characterCode && characterCode <= 57 /* '9' */) || - (65 /* 'A' */ <= characterCode && characterCode <= 90 /* 'Z' */) || - (97 /* 'a' */ <= characterCode && characterCode <= 122 /* 'z' */); + return ( + (48 /* '0' */ <= characterCode && characterCode <= 57) /* '9' */ || + (65 /* 'A' */ <= characterCode && characterCode <= 90) /* 'Z' */ || + (97 /* 'a' */ <= characterCode && characterCode <= 122) /* 'z' */ + ); } /** @@ -441,39 +442,38 @@ export class URLTokenizer { this._currentToken = undefined; } else { switch (this._currentState) { - case "SCHEME": - nextScheme(this); - break; + case "SCHEME": + nextScheme(this); + break; - case "SCHEME_OR_HOST": - nextSchemeOrHost(this); - break; + case "SCHEME_OR_HOST": + nextSchemeOrHost(this); + break; - case "HOST": - nextHost(this); - break; + case "HOST": + nextHost(this); + break; - case "PORT": - nextPort(this); - break; + case "PORT": + nextPort(this); + break; - case "PATH": - nextPath(this); - break; + case "PATH": + nextPath(this); + break; - case "QUERY": - nextQuery(this); - break; + case "QUERY": + nextQuery(this); + break; - default: - throw new Error(`Unrecognized URLTokenizerState: ${this._currentState}`); + default: + throw new Error(`Unrecognized URLTokenizerState: ${this._currentState}`); } } return !!this._currentToken; } } - /** * Read the remaining characters from this Tokenizer's character stream. */ @@ -558,7 +558,10 @@ function readWhileLetterOrDigit(tokenizer: URLTokenizer): string { * the end of the character stream is reached. */ function readUntilCharacter(tokenizer: URLTokenizer, ...terminatingCharacters: string[]): string { - return readWhile(tokenizer, (character: string) => terminatingCharacters.indexOf(character) === -1); + return readWhile( + tokenizer, + (character: string) => terminatingCharacters.indexOf(character) === -1 + ); } function nextScheme(tokenizer: URLTokenizer): void { diff --git a/lib/util/base64.ts b/lib/util/base64.ts index 03b3bdc..ea0c2e0 100644 --- a/lib/util/base64.ts +++ b/lib/util/base64.ts @@ -16,7 +16,7 @@ export function encodeString(value: string): string { export function encodeByteArray(value: Uint8Array): string { // Buffer.from accepts | -- the TypeScript definition is off here // https://nodejs.org/api/buffer.html#buffer_class_method_buffer_from_arraybuffer_byteoffset_length - const bufferValue = (value instanceof Buffer) ? value : Buffer.from(value.buffer as ArrayBuffer); + const bufferValue = value instanceof Buffer ? value : Buffer.from(value.buffer as ArrayBuffer); return bufferValue.toString("base64"); } diff --git a/lib/util/constants.ts b/lib/util/constants.ts index 2b67f64..3dda031 100644 --- a/lib/util/constants.ts +++ b/lib/util/constants.ts @@ -55,12 +55,12 @@ export const Constants = { POST: "POST", MERGE: "MERGE", HEAD: "HEAD", - PATCH: "PATCH" + PATCH: "PATCH", }, StatusCodes: { - TooManyRequests: 429 - } + TooManyRequests: 429, + }, }, /** @@ -93,6 +93,6 @@ export const Constants = { * @const * @type {string} */ - USER_AGENT: "User-Agent" - } + USER_AGENT: "User-Agent", + }, }; diff --git a/lib/util/utils.ts b/lib/util/utils.ts index 71a6cb0..57f9716 100644 --- a/lib/util/utils.ts +++ b/lib/util/utils.ts @@ -10,7 +10,11 @@ import { Constants } from "./constants"; /** * A constant that indicates whether the environment is node.js or browser based. */ -export const isNode = (typeof process !== "undefined") && !!process.version && !!process.versions && !!process.versions.node; +export const isNode = + typeof process !== "undefined" && + !!process.version && + !!process.versions && + !!process.versions.node; /** * Checks if a parsed URL is HTTPS @@ -77,7 +81,10 @@ export function stripRequest(request: WebResourceLike): WebResourceLike { * @return {boolean} True if the uuid is valid; false otherwise. */ export function isValidUuid(uuid: string): boolean { - const validUuidRegex = new RegExp("^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$", "ig"); + const validUuidRegex = new RegExp( + "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$", + "ig" + ); return validUuidRegex.test(uuid); } @@ -89,7 +96,7 @@ export function isValidUuid(uuid: string): boolean { * * @return {any[]} An array of values of the given object. */ -export function objectValues(obj: { [key: string]: any; }): any[] { +export function objectValues(obj: { [key: string]: any }): any[] { const result: any[] = []; if (obj && obj instanceof Object) { for (const key in obj) { @@ -98,8 +105,13 @@ export function objectValues(obj: { [key: string]: any; }): any[] { } } } else { - throw new Error(`The provided object ${JSON.stringify(obj, undefined, 2)} is not a valid object that can be ` + - `enumerated to provide its values as an array.`); + throw new Error( + `The provided object ${JSON.stringify( + obj, + undefined, + 2 + )} is not a valid object that can be ` + `enumerated to provide its values as an array.` + ); } return result; } @@ -140,7 +152,7 @@ export function executePromisesSequentially(promiseFactories: Array, kickst * * @returns {object} Returns the merged target object. */ -export function mergeObjects(source: { [key: string]: any; }, target: { [key: string]: any; }) { +export function mergeObjects(source: { [key: string]: any }, target: { [key: string]: any }) { Object.keys(source).forEach((key) => { target[key] = source[key]; }); @@ -168,7 +180,12 @@ export interface ServiceCallback { * @param {WebResourceLike} [request] The raw/actual request sent to the server if an error did not occur. * @param {HttpOperationResponse} [response] The raw/actual response from the server if an error did not occur. */ - (err: Error | RestError | null, result?: TResult, request?: WebResourceLike, response?: HttpOperationResponse): void; + ( + err: Error | RestError | null, + result?: TResult, + request?: WebResourceLike, + response?: HttpOperationResponse + ): void; } /** @@ -182,11 +199,14 @@ export function promiseToCallback(promise: Promise): Function { throw new Error("The provided input is not a Promise."); } return (cb: Function): void => { - promise.then((data: any) => { - cb(undefined, data); - }, (err: Error) => { - cb(err); - }); + promise.then( + (data: any) => { + cb(undefined, data); + }, + (err: Error) => { + cb(err); + } + ); }; } @@ -200,11 +220,14 @@ export function promiseToServiceCallback(promise: Promise): void => { - promise.then((data: HttpOperationResponse) => { - process.nextTick(cb, undefined, data.parsedBody as T, data.request, data); - }, (err: Error) => { - process.nextTick(cb, err); - }); + promise.then( + (data: HttpOperationResponse) => { + process.nextTick(cb, undefined, data.parsedBody as T, data.request, data); + }, + (err: Error) => { + process.nextTick(cb, err); + } + ); }; } @@ -221,8 +244,8 @@ export function prepareXMLRootList(obj: any, elementName: string) { * @param {Array} sourceCtors An array of source objects from which the properties need to be taken. */ export function applyMixins(targetCtor: any, sourceCtors: any[]): void { - sourceCtors.forEach(sourceCtors => { - Object.getOwnPropertyNames(sourceCtors.prototype).forEach(name => { + sourceCtors.forEach((sourceCtors) => { + Object.getOwnPropertyNames(sourceCtors.prototype).forEach((name) => { targetCtor.prototype[name] = sourceCtors.prototype[name]; }); }); @@ -246,7 +269,11 @@ export function isDuration(value: string): boolean { * @param {string} replaceValue The value to replace searchValue with in the value argument. * @returns {string | undefined} The value where each instance of searchValue was replaced with replacedValue. */ -export function replaceAll(value: string | undefined, searchValue: string, replaceValue: string): string | undefined { +export function replaceAll( + value: string | undefined, + searchValue: string, + replaceValue: string +): string | undefined { return !value || !searchValue ? value : value.split(searchValue).join(replaceValue || ""); } @@ -258,4 +285,4 @@ export function replaceAll(value: string | undefined, searchValue: string, repla */ export function isPrimitiveType(value: any): boolean { return (typeof value !== "object" && typeof value !== "function") || value === null; -} \ No newline at end of file +} diff --git a/lib/util/xml.browser.ts b/lib/util/xml.browser.ts index 5fdb2a4..3a36963 100644 --- a/lib/util/xml.browser.ts +++ b/lib/util/xml.browser.ts @@ -16,7 +16,8 @@ export function parseXML(str: string): Promise { let errorNS = ""; try { - errorNS = parser.parseFromString("INVALID", "text/xml").getElementsByTagName("parsererror")[0].namespaceURI!; + errorNS = parser.parseFromString("INVALID", "text/xml").getElementsByTagName("parsererror")[0] + .namespaceURI!; } catch (ignored) { // Most browsers will return a document containing , but IE will throw. } @@ -48,7 +49,12 @@ function domToObject(node: Node): any { const childNodeCount: number = node.childNodes.length; const firstChildNode: Node = node.childNodes[0]; - const onlyChildTextValue: string | undefined = (firstChildNode && childNodeCount === 1 && firstChildNode.nodeType === Node.TEXT_NODE && firstChildNode.nodeValue) || undefined; + const onlyChildTextValue: string | undefined = + (firstChildNode && + childNodeCount === 1 && + firstChildNode.nodeType === Node.TEXT_NODE && + firstChildNode.nodeValue) || + undefined; const elementWithAttributes: Element | undefined = asElementWithAttributes(node); if (elementWithAttributes) { @@ -93,12 +99,14 @@ const doc = document.implementation.createDocument(null, null, null); const serializer = new XMLSerializer(); export function stringifyXML(obj: any, opts?: { rootName?: string }) { - const rootName = opts && opts.rootName || "root"; + const rootName = (opts && opts.rootName) || "root"; const dom = buildNode(obj, rootName)[0]; - return '' + serializer.serializeToString(dom); + return ( + '' + serializer.serializeToString(dom) + ); } -function buildAttributes(attrs: { [key: string]: { toString(): string; } }): Attr[] { +function buildAttributes(attrs: { [key: string]: { toString(): string } }): Attr[] { const result = []; for (const key of Object.keys(attrs)) { const attr = doc.createAttribute(key); @@ -113,8 +121,7 @@ function buildNode(obj: any, elementName: string): Node[] { const elem = doc.createElement(elementName); elem.textContent = obj.toString(); return [elem]; - } - else if (Array.isArray(obj)) { + } else if (Array.isArray(obj)) { const result = []; for (const arrayElem of obj) { for (const child of buildNode(arrayElem, elementName)) { @@ -136,8 +143,7 @@ function buildNode(obj: any, elementName: string): Node[] { } } return [elem]; - } - else { + } else { throw new Error(`Illegal value passed to buildObject: ${obj}`); } } diff --git a/lib/util/xml.ts b/lib/util/xml.ts index 0dc396a..829e5e0 100644 --- a/lib/util/xml.ts +++ b/lib/util/xml.ts @@ -7,8 +7,8 @@ export function stringifyXML(obj: any, opts?: { rootName?: string }) { const builder = new xml2js.Builder({ rootName: (opts || {}).rootName, renderOpts: { - pretty: false - } + pretty: false, + }, }); return builder.buildObject(obj); } @@ -17,7 +17,7 @@ export function parseXML(str: string): Promise { const xmlParser = new xml2js.Parser({ explicitArray: false, explicitCharkey: false, - explicitRoot: false + explicitRoot: false, }); return new Promise((resolve, reject) => { if (!str) { diff --git a/lib/webResource.ts b/lib/webResource.ts index 8ce5ff8..ff5aab1 100644 --- a/lib/webResource.ts +++ b/lib/webResource.ts @@ -9,8 +9,21 @@ import { HttpOperationResponse } from "./httpOperationResponse"; import { OperationResponse } from "./operationResponse"; import { AgentSettings, ProxySettings } from "./serviceClient"; -export type HttpMethods = "GET" | "PUT" | "POST" | "DELETE" | "PATCH" | "HEAD" | "OPTIONS" | "TRACE"; -export type HttpRequestBody = Blob | string | ArrayBuffer | ArrayBufferView | (() => NodeJS.ReadableStream); +export type HttpMethods = + | "GET" + | "PUT" + | "POST" + | "DELETE" + | "PATCH" + | "HEAD" + | "OPTIONS" + | "TRACE"; +export type HttpRequestBody = + | Blob + | string + | ArrayBuffer + | ArrayBufferView + | (() => NodeJS.ReadableStream); /** * Fired in response to upload or download progress. @@ -19,7 +32,7 @@ export type TransferProgressEvent = { /** * The number of bytes loaded so far. */ - loadedBytes: number + loadedBytes: number; }; /** @@ -30,8 +43,16 @@ export interface AbortSignalLike { readonly aborted: boolean; dispatchEvent: (event: Event) => boolean; onabort: ((this: AbortSignalLike, ev: Event) => any) | null; - addEventListener: (type: "abort", listener: (this: AbortSignalLike, ev: Event) => any, options?: any) => void; - removeEventListener: (type: "abort", listener: (this: AbortSignalLike, ev: Event) => any, options?: any) => void; + addEventListener: ( + type: "abort", + listener: (this: AbortSignalLike, ev: Event) => any, + options?: any + ) => void; + removeEventListener: ( + type: "abort", + listener: (this: AbortSignalLike, ev: Event) => any, + options?: any + ) => void; } /** @@ -178,9 +199,12 @@ export class WebResource { * HttpOperationResponse combination. If this is undefined, then a simple status code lookup will * be used. */ - operationResponseGetter?: (operationSpec: OperationSpec, response: HttpOperationResponse) => (undefined | OperationResponse); + operationResponseGetter?: ( + operationSpec: OperationSpec, + response: HttpOperationResponse + ) => undefined | OperationResponse; formData?: any; - query?: { [key: string]: any; }; + query?: { [key: string]: any }; operationSpec?: OperationSpec; withCredentials: boolean; timeout: number; @@ -200,8 +224,8 @@ export class WebResource { url?: string, method?: HttpMethods, body?: any, - query?: { [key: string]: any; }, - headers?: { [key: string]: any; } | HttpHeadersLike, + query?: { [key: string]: any }, + headers?: { [key: string]: any } | HttpHeadersLike, streamResponseBody?: boolean, withCredentials?: boolean, abortSignal?: AbortSignalLike, @@ -210,12 +234,12 @@ export class WebResource { onDownloadProgress?: (progress: TransferProgressEvent) => void, proxySettings?: ProxySettings, keepAlive?: boolean, - agentSettings?: AgentSettings) { - + agentSettings?: AgentSettings + ) { this.streamResponseBody = streamResponseBody; this.url = url || ""; this.method = method || "GET"; - this.headers = (isHttpHeadersLike(headers) ? headers : new HttpHeaders(headers)); + this.headers = isHttpHeadersLike(headers) ? headers : new HttpHeaders(headers); this.body = body; this.query = query; this.formData = undefined; @@ -258,18 +282,22 @@ export class WebResource { } if (options.url && options.pathTemplate) { - throw new Error("options.url and options.pathTemplate are mutually exclusive. Please provide exactly one of them."); + throw new Error( + "options.url and options.pathTemplate are mutually exclusive. Please provide exactly one of them." + ); } - - if ((options.pathTemplate == undefined || typeof options.pathTemplate.valueOf() !== "string") && (options.url == undefined || typeof options.url.valueOf() !== "string")) { + if ( + (options.pathTemplate == undefined || typeof options.pathTemplate.valueOf() !== "string") && + (options.url == undefined || typeof options.url.valueOf() !== "string") + ) { throw new Error("Please provide exactly one of options.pathTemplate or options.url."); } // set the url if it is provided. if (options.url) { if (typeof options.url !== "string") { - throw new Error("options.url must be of type \"string\"."); + throw new Error('options.url must be of type "string".'); } this.url = options.url; } @@ -278,35 +306,55 @@ export class WebResource { if (options.method) { const validMethods = ["GET", "PUT", "HEAD", "DELETE", "OPTIONS", "POST", "PATCH", "TRACE"]; if (validMethods.indexOf(options.method.toUpperCase()) === -1) { - throw new Error("The provided method \"" + options.method + "\" is invalid. Supported HTTP methods are: " + JSON.stringify(validMethods)); + throw new Error( + 'The provided method "' + + options.method + + '" is invalid. Supported HTTP methods are: ' + + JSON.stringify(validMethods) + ); } } - this.method = (options.method.toUpperCase() as HttpMethods); + this.method = options.method.toUpperCase() as HttpMethods; // construct the url if path template is provided if (options.pathTemplate) { const { pathTemplate, pathParameters } = options; if (typeof pathTemplate !== "string") { - throw new Error("options.pathTemplate must be of type \"string\"."); + throw new Error('options.pathTemplate must be of type "string".'); } if (!options.baseUrl) { options.baseUrl = "https://management.azure.com"; } const baseUrl = options.baseUrl; - let url = baseUrl + (baseUrl.endsWith("/") ? "" : "/") + (pathTemplate.startsWith("/") ? pathTemplate.slice(1) : pathTemplate); - const segments = url.match(/({\w*\s*\w*})/ig); + let url = + baseUrl + + (baseUrl.endsWith("/") ? "" : "/") + + (pathTemplate.startsWith("/") ? pathTemplate.slice(1) : pathTemplate); + const segments = url.match(/({\w*\s*\w*})/gi); if (segments && segments.length) { if (!pathParameters) { - throw new Error(`pathTemplate: ${pathTemplate} has been provided. Hence, options.pathParameters must also be provided.`); + throw new Error( + `pathTemplate: ${pathTemplate} has been provided. Hence, options.pathParameters must also be provided.` + ); } segments.forEach(function (item) { const pathParamName = item.slice(1, -1); const pathParam = (pathParameters as { [key: string]: any })[pathParamName]; - if (pathParam === null || pathParam === undefined || !(typeof pathParam === "string" || typeof pathParam === "object")) { - throw new Error(`pathTemplate: ${pathTemplate} contains the path parameter ${pathParamName}` + - ` however, it is not present in ${pathParameters} - ${JSON.stringify(pathParameters, undefined, 2)}.` + - `The value of the path parameter can either be a "string" of the form { ${pathParamName}: "some sample value" } or ` + - `it can be an "object" of the form { "${pathParamName}": { value: "some sample value", skipUrlEncoding: true } }.`); + if ( + pathParam === null || + pathParam === undefined || + !(typeof pathParam === "string" || typeof pathParam === "object") + ) { + throw new Error( + `pathTemplate: ${pathTemplate} contains the path parameter ${pathParamName}` + + ` however, it is not present in ${pathParameters} - ${JSON.stringify( + pathParameters, + undefined, + 2 + )}.` + + `The value of the path parameter can either be a "string" of the form { ${pathParamName}: "some sample value" } or ` + + `it can be an "object" of the form { "${pathParamName}": { value: "some sample value", skipUrlEncoding: true } }.` + ); } if (typeof pathParam.valueOf() === "string") { @@ -315,7 +363,9 @@ export class WebResource { if (typeof pathParam.valueOf() === "object") { if (!pathParam.value) { - throw new Error(`options.pathParameters[${pathParamName}] is of type "object" but it does not contain a "value" property.`); + throw new Error( + `options.pathParameters[${pathParamName}] is of type "object" but it does not contain a "value" property.` + ); } if (pathParam.skipUrlEncoding) { url = url.replace(item, pathParam.value); @@ -332,9 +382,11 @@ export class WebResource { if (options.queryParameters) { const queryParameters = options.queryParameters; if (typeof queryParameters !== "object") { - throw new Error(`options.queryParameters must be of type object. It should be a JSON object ` + - `of "query-parameter-name" as the key and the "query-parameter-value" as the value. ` + - `The "query-parameter-value" may be fo type "string" or an "object" of the form { value: "query-parameter-value", skipUrlEncoding: true }.`); + throw new Error( + `options.queryParameters must be of type object. It should be a JSON object ` + + `of "query-parameter-name" as the key and the "query-parameter-value" as the value. ` + + `The "query-parameter-value" may be fo type "string" or an "object" of the form { value: "query-parameter-value", skipUrlEncoding: true }.` + ); } // append question mark if it is not present in the url if (this.url && this.url.indexOf("?") === -1) { @@ -350,10 +402,11 @@ export class WebResource { if (typeof queryParam === "string") { queryParams.push(queryParamName + "=" + encodeURIComponent(queryParam)); this.query[queryParamName] = encodeURIComponent(queryParam); - } - else if (typeof queryParam === "object") { + } else if (typeof queryParam === "object") { if (!queryParam.value) { - throw new Error(`options.queryParameters[${queryParamName}] is of type "object" but it does not contain a "value" property.`); + throw new Error( + `options.queryParameters[${queryParamName}] is of type "object" but it does not contain a "value" property.` + ); } if (queryParam.skipUrlEncoding) { queryParams.push(queryParamName + "=" + queryParam.value); @@ -364,7 +417,7 @@ export class WebResource { } } } - }// end-of-for + } // end-of-for // append the queryString this.url += queryParams.join("&"); } @@ -403,7 +456,11 @@ export class WebResource { } } else { if (options.serializationMapper) { - this.body = new Serializer(options.mappers).serialize(options.serializationMapper, options.body, "requestBody"); + this.body = new Serializer(options.mappers).serialize( + options.serializationMapper, + options.body, + "requestBody" + ); } if (!options.disableJsonStringifyOnBody) { this.body = JSON.stringify(options.body); @@ -437,7 +494,8 @@ export class WebResource { this.onDownloadProgress, this.proxySettings, this.keepAlive, - this.agentSettings); + this.agentSettings + ); if (this.formData) { result.formData = this.formData; diff --git a/lib/xhrHttpClient.ts b/lib/xhrHttpClient.ts index 245deba..698d701 100644 --- a/lib/xhrHttpClient.ts +++ b/lib/xhrHttpClient.ts @@ -94,7 +94,7 @@ export class XhrHttpClient implements HttpClient { request, status: xhr.status, headers: parseHeaders(xhr), - blobBody + blobBody, }); } }); @@ -102,30 +102,40 @@ export class XhrHttpClient implements HttpClient { }); } else { return new Promise(function (resolve, reject) { - xhr.addEventListener("load", () => resolve({ - request, - status: xhr.status, - headers: parseHeaders(xhr), - bodyAsText: xhr.responseText - })); + xhr.addEventListener("load", () => + resolve({ + request, + status: xhr.status, + headers: parseHeaders(xhr), + bodyAsText: xhr.responseText, + }) + ); rejectOnTerminalEvent(request, xhr, reject); }); } } } -function addProgressListener(xhr: XMLHttpRequestEventTarget, listener?: (progress: TransferProgressEvent) => void) { +function addProgressListener( + xhr: XMLHttpRequestEventTarget, + listener?: (progress: TransferProgressEvent) => void +) { if (listener) { - xhr.addEventListener("progress", rawEvent => listener({ - loadedBytes: rawEvent.loaded - })); + xhr.addEventListener("progress", (rawEvent) => + listener({ + loadedBytes: rawEvent.loaded, + }) + ); } } // exported locally for testing export function parseHeaders(xhr: XMLHttpRequest) { const responseHeaders = new HttpHeaders(); - const headerLines = xhr.getAllResponseHeaders().trim().split(/[\r\n]+/); + const headerLines = xhr + .getAllResponseHeaders() + .trim() + .split(/[\r\n]+/); for (const line of headerLines) { const index = line.indexOf(":"); const headerName = line.slice(0, index); @@ -135,8 +145,34 @@ export function parseHeaders(xhr: XMLHttpRequest) { return responseHeaders; } -function rejectOnTerminalEvent(request: WebResourceLike, xhr: XMLHttpRequest, reject: (err: any) => void) { - xhr.addEventListener("error", () => reject(new RestError(`Failed to send request to ${request.url}`, RestError.REQUEST_SEND_ERROR, undefined, request))); - xhr.addEventListener("abort", () => reject(new RestError("The request was aborted", RestError.REQUEST_ABORTED_ERROR, undefined, request))); - xhr.addEventListener("timeout", () => reject(new RestError(`timeout of ${xhr.timeout}ms exceeded`, RestError.REQUEST_SEND_ERROR, undefined, request))); +function rejectOnTerminalEvent( + request: WebResourceLike, + xhr: XMLHttpRequest, + reject: (err: any) => void +) { + xhr.addEventListener("error", () => + reject( + new RestError( + `Failed to send request to ${request.url}`, + RestError.REQUEST_SEND_ERROR, + undefined, + request + ) + ) + ); + xhr.addEventListener("abort", () => + reject( + new RestError("The request was aborted", RestError.REQUEST_ABORTED_ERROR, undefined, request) + ) + ); + xhr.addEventListener("timeout", () => + reject( + new RestError( + `timeout of ${xhr.timeout}ms exceeded`, + RestError.REQUEST_SEND_ERROR, + undefined, + request + ) + ) + ); } diff --git a/package.json b/package.json index 9c59464..be9bc8c 100644 --- a/package.json +++ b/package.json @@ -100,6 +100,7 @@ "mocha-multi-reporters": "^1.1.7", "npm-run-all": "^4.1.5", "nyc": "^14.1.1", + "prettier": "2.2.1", "rollup": "^1.16.6", "rollup-plugin-commonjs": "^10.0.1", "rollup-plugin-json": "^4.0.0", @@ -139,6 +140,7 @@ "build:rollup": "rollup -c rollup.config.ts", "build:minify-browser": "terser -c -m --comments --source-map \"content='./dist/msRest.browser.js.map'\" -o ./dist/msRest.browser.min.js ./dist/msRest.browser.js", "build:test-browser": "webpack --config webpack.testconfig.ts", + "format": "prettier --write \"./**/*.ts\"", "test": "run-p test:tslint test:unit test:karma", "test:tslint": "tslint -p .", "test:unit": "nyc mocha", diff --git a/rollup.config.ts b/rollup.config.ts index 594bd88..92faeae 100644 --- a/rollup.config.ts +++ b/rollup.config.ts @@ -37,7 +37,7 @@ const nodeConfig = { file: "./dist/msRest.node.js", format: "cjs", sourcemap: true, - banner + banner, }, plugins: [ nodeResolve({ @@ -48,9 +48,9 @@ const nodeConfig = { json(), visualizer({ filename: "dist/node-stats.html", - sourcemap: true - }) - ] + sourcemap: true, + }), + ], }; /** @@ -64,19 +64,19 @@ const browserConfig = { format: "umd", name: "msRest", sourcemap: true, - banner + banner, }, plugins: [ nodeResolve({ - mainFields: ["module", "main", "browser"] + mainFields: ["module", "main", "browser"], }), commonjs(), sourcemaps(), visualizer({ filename: "dist/browser-stats.html", - sourcemap: true - }) - ] + sourcemap: true, + }), + ], }; export default [nodeConfig, browserConfig]; diff --git a/samples/node-sample.ts b/samples/node-sample.ts index ecc31f6..5923c8b 100644 --- a/samples/node-sample.ts +++ b/samples/node-sample.ts @@ -3,7 +3,7 @@ import * as msRest from "../lib/msRest"; const clientOptions: msRest.ServiceClientOptions = { // add log policy to list of default factories. - requestPolicyFactories: (factories) => factories.concat([msRest.logPolicy()]) + requestPolicyFactories: (factories) => factories.concat([msRest.logPolicy()]), }; const subscriptionId = process.env["AZURE_SUBSCRIPTION_ID"] || "subscriptionId"; @@ -17,10 +17,9 @@ const creds = new msRest.TokenCredentials(token); const client = new msRest.ServiceClient(creds, clientOptions); const req: msRest.RequestPrepareOptions = { url: `https://management.azure.com/subscriptions/${subscriptionId}/providers/Microsoft.Storage/storageAccounts?api-version=2015-06-15`, - method: "GET" + method: "GET", }; client.sendRequest(req).then(function (res: msRest.HttpOperationResponse) { console.log(res.bodyAsText); }); - diff --git a/test/credentialTests.ts b/test/credentialTests.ts index 7c375dd..c195758 100644 --- a/test/credentialTests.ts +++ b/test/credentialTests.ts @@ -20,7 +20,9 @@ describe("Token credentials", () => { creds.signRequest(request).then((signedRequest: msRest.WebResourceLike) => { signedRequest.headers.get("authorization")!.should.exist; - signedRequest.headers.get("authorization")!.should.match(new RegExp("^Bearer\\s+" + dummyToken + "$")); + signedRequest.headers + .get("authorization")! + .should.match(new RegExp("^Bearer\\s+" + dummyToken + "$")); done(); }); }); @@ -30,14 +32,15 @@ describe("Token credentials", () => { const request = new msRest.WebResource(); creds.signRequest(request).then((signedRequest: msRest.WebResourceLike) => { signedRequest.headers.get("authorization")!.should.exist; - signedRequest.headers.get("authorization")!.should.match(new RegExp("^" + fakeScheme + "\\s+" + dummyToken + "$")); + signedRequest.headers + .get("authorization")! + .should.match(new RegExp("^" + fakeScheme + "\\s+" + dummyToken + "$")); done(); }); }); }); describe("construction", () => { - it("should succeed with token", () => { (() => { new TokenCredentials(dummyToken); @@ -66,7 +69,9 @@ describe("Basic Authentication credentials", () => { const request = new msRest.WebResource(); creds.signRequest(request).then((signedRequest: msRest.WebResourceLike) => { signedRequest.headers.get("authorization")!.should.exist; - signedRequest.headers.get("authorization")!.should.match(new RegExp("^Basic\\s+" + encodedCredentials + "$")); + signedRequest.headers + .get("authorization")! + .should.match(new RegExp("^Basic\\s+" + encodedCredentials + "$")); done(); }); }); @@ -77,7 +82,9 @@ describe("Basic Authentication credentials", () => { creds.signRequest(request).then((signedRequest: msRest.WebResourceLike) => { signedRequest.headers.get("authorization")!.should.exist; - signedRequest.headers.get("authorization")!.should.match(new RegExp("^" + fakeScheme + "\\s+" + encodedCredentials + "$")); + signedRequest.headers + .get("authorization")! + .should.match(new RegExp("^" + fakeScheme + "\\s+" + encodedCredentials + "$")); done(); }); }); @@ -94,7 +101,7 @@ describe("Basic Authentication credentials", () => { describe("ApiKey credentials", () => { describe("usage", function () { it("should set header parameters properly in request", async function () { - const creds = new ApiKeyCredentials({inHeader: {"key1": "value1", "key2": "value2"}}); + const creds = new ApiKeyCredentials({ inHeader: { key1: "value1", key2: "value2" } }); const request = new msRest.WebResource(); request.headers = new msRest.HttpHeaders(); @@ -107,10 +114,10 @@ describe("Basic Authentication credentials", () => { }); it("should set query parameters properly in the request url without any query parameters", async function () { - const creds = new ApiKeyCredentials({inQuery: {"key1": "value1", "key2": "value2"}}); + const creds = new ApiKeyCredentials({ inQuery: { key1: "value1", key2: "value2" } }); const request = { headers: {}, - url: "https://example.com" + url: "https://example.com", } as msRest.WebResource; await creds.signRequest(request); @@ -118,10 +125,10 @@ describe("Basic Authentication credentials", () => { }); it("should set query parameters properly in the request url with existing query parameters", async function () { - const creds = new ApiKeyCredentials({inQuery: {"key1": "value1", "key2": "value2"}}); + const creds = new ApiKeyCredentials({ inQuery: { key1: "value1", key2: "value2" } }); const request = { headers: {}, - url: "https://example.com?q1=v2" + url: "https://example.com?q1=v2", } as msRest.WebResource; await creds.signRequest(request); @@ -130,25 +137,24 @@ describe("Basic Authentication credentials", () => { }); describe("construction", function () { - it("should fail with options.inHeader and options.inQuery set to null or undefined", function (done) { (function () { new ApiKeyCredentials({ inHeader: undefined, inQuery: undefined } as any); - }).should.throw(); + }.should.throw()); done(); }); it("should fail without options", function (done) { (function () { new (ApiKeyCredentials as any)(); - }).should.throw(); + }.should.throw()); done(); }); it("should fail with empty options", function (done) { (function () { new ApiKeyCredentials({}); - }).should.throw(); + }.should.throw()); done(); }); }); diff --git a/test/data/TestClient/lib/models/mappers.ts b/test/data/TestClient/lib/models/mappers.ts index 52fcc8c..a0db463 100644 --- a/test/data/TestClient/lib/models/mappers.ts +++ b/test/data/TestClient/lib/models/mappers.ts @@ -16,29 +16,29 @@ internalMappers.Cat = { required: false, serializedName: "id", type: { - name: "Number" - } + name: "Number", + }, }, name: { required: false, serializedName: "name", type: { - name: "String" - } + name: "String", + }, }, pettype: { required: true, serializedName: "pet\\.type", type: { - name: "String" - } + name: "String", + }, }, color: { required: false, serializedName: "color", type: { - name: "String" - } + name: "String", + }, }, hates: { required: false, @@ -50,13 +50,13 @@ internalMappers.Cat = { serializedName: "DogElementType", type: { name: "Composite", - className: "Dog" - } - } - } - } - } - } + className: "Dog", + }, + }, + }, + }, + }, + }, }; internalMappers.Dog = { required: false, @@ -69,32 +69,32 @@ internalMappers.Dog = { required: false, serializedName: "id", type: { - name: "Number" - } + name: "Number", + }, }, name: { required: false, serializedName: "name", type: { - name: "String" - } + name: "String", + }, }, pettype: { required: true, serializedName: "pet\\.type", type: { - name: "String" - } + name: "String", + }, }, food: { required: false, serializedName: "food", type: { - name: "String" - } - } - } - } + name: "String", + }, + }, + }, + }, }; internalMappers.Fish = { required: false, @@ -103,7 +103,7 @@ internalMappers.Fish = { name: "Composite", polymorphicDiscriminator: { serializedName: "fish.type", - clientName: "fishtype" + clientName: "fishtype", }, uberParent: "Fish", className: "Fish", @@ -112,15 +112,15 @@ internalMappers.Fish = { required: false, serializedName: "species", type: { - name: "String" - } + name: "String", + }, }, length: { required: true, serializedName: "length", type: { - name: "Number" - } + name: "Number", + }, }, siblings: { required: false, @@ -134,23 +134,23 @@ internalMappers.Fish = { name: "Composite", polymorphicDiscriminator: { serializedName: "fish.type", - clientName: "fishtype" + clientName: "fishtype", }, uberParent: "Fish", - className: "Fish" - } - } - } + className: "Fish", + }, + }, + }, }, fishtype: { required: true, serializedName: "fish\\.type", type: { - name: "String" - } - } - } - } + name: "String", + }, + }, + }, + }, }; internalMappers.Invoice = { required: false, @@ -163,15 +163,15 @@ internalMappers.Invoice = { serializedName: "invoiceId", required: true, type: { - name: "Number" - } + name: "Number", + }, }, invDate: { serializedName: "invDate", required: false, type: { - name: "Date" - } + name: "Date", + }, }, invProducts: { serializedName: "invProducts", @@ -184,15 +184,15 @@ internalMappers.Invoice = { value: { type: { name: "Composite", - className: "Product" - } - } - } - } - } - } - } - } + className: "Product", + }, + }, + }, + }, + }, + }, + }, + }, }; internalMappers.Pet = { required: false, @@ -206,25 +206,25 @@ internalMappers.Pet = { required: false, serializedName: "id", type: { - name: "Number" - } + name: "Number", + }, }, name: { required: false, serializedName: "name", type: { - name: "String" - } + name: "String", + }, }, pettype: { required: true, serializedName: "pet\\.type", type: { - name: "String" - } - } - } - } + name: "String", + }, + }, + }, + }, }; internalMappers.PetAP = { required: false, @@ -233,8 +233,8 @@ internalMappers.PetAP = { name: "Composite", additionalProperties: { type: { - name: "String" - } + name: "String", + }, }, className: "PetAP", modelProperties: { @@ -242,15 +242,15 @@ internalMappers.PetAP = { required: true, serializedName: "id", type: { - name: "Number" - } + name: "Number", + }, }, name: { required: false, serializedName: "name", type: { - name: "String" - } + name: "String", + }, }, eyeColor: { required: true, @@ -258,31 +258,31 @@ internalMappers.PetAP = { isConstant: true, defaultValue: "brown", type: { - name: "String" - } + name: "String", + }, }, favoriteFood: { required: false, serializedName: "favoriteFood", defaultValue: "bones", type: { - name: "String" - } + name: "String", + }, }, status: { required: false, readOnly: true, serializedName: "status", type: { - name: "Boolean" - } + name: "Boolean", + }, }, odatalocation: { required: true, serializedName: "@odata\\.location", type: { - name: "String" - } + name: "String", + }, }, additionalProperties1: { required: false, @@ -293,13 +293,13 @@ internalMappers.PetAP = { required: false, serializedName: "NumberElementType", type: { - name: "Number" - } - } - } - } - } - } + name: "Number", + }, + }, + }, + }, + }, + }, }; internalMappers.PetGallery = { required: false, @@ -312,15 +312,15 @@ internalMappers.PetGallery = { required: false, serializedName: "id", type: { - name: "Number" - } + name: "Number", + }, }, name: { required: false, serializedName: "name", type: { - name: "String" - } + name: "String", + }, }, pets: { required: false, @@ -334,13 +334,13 @@ internalMappers.PetGallery = { name: "Composite", polymorphicDiscriminator: "pet.type", uberParent: "Pet", - className: "Pet" - } - } - } - } - } - } + className: "Pet", + }, + }, + }, + }, + }, + }, }; internalMappers.Product = { required: false, @@ -351,33 +351,31 @@ internalMappers.Product = { modelProperties: { id: { serializedName: "id", - constraints: { - - }, + constraints: {}, required: true, type: { - name: "Number" - } + name: "Number", + }, }, name: { serializedName: "name", required: true, type: { - name: "String" + name: "String", }, constraints: { MaxLength: 256, MinLength: 1, - Pattern: /^[A-Za-z0-9-._]+$/ - } + Pattern: /^[A-Za-z0-9-._]+$/, + }, }, provisioningState: { serializedName: "properties.provisioningState", required: false, type: { name: "Enum", - allowedValues: ["Creating", "Failed", "Succeeded"] - } + allowedValues: ["Creating", "Failed", "Succeeded"], + }, }, tags: { serializedName: "tags", @@ -386,25 +384,25 @@ internalMappers.Product = { name: "Dictionary", value: { type: { - name: "String" - } - } - } + name: "String", + }, + }, + }, }, dispatchTime: { serializedName: "dispatchTime", required: false, type: { - name: "DateTime" - } + name: "DateTime", + }, }, invoiceInfo: { serializedName: "invoiceInfo", required: false, type: { name: "Composite", - className: "Invoice" - } + className: "Invoice", + }, }, subProducts: { serializedName: "subProducts", @@ -414,13 +412,13 @@ internalMappers.Product = { element: { type: { name: "Composite", - className: "SubProduct" - } - } - } - } - } - } + className: "SubProduct", + }, + }, + }, + }, + }, + }, }; internalMappers.ProductListResult = { required: false, @@ -437,13 +435,13 @@ internalMappers.ProductListResult = { element: { type: { name: "Composite", - className: "Product" - } - } - } - } - } - } + className: "Product", + }, + }, + }, + }, + }, + }, }; internalMappers.ProductListResultNextLink = { required: false, @@ -460,20 +458,20 @@ internalMappers.ProductListResultNextLink = { element: { type: { name: "Composite", - className: "Product" - } - } - } + className: "Product", + }, + }, + }, }, nextLink: { serializedName: "nextLink", required: false, type: { - name: "String" - } - } - } - } + name: "String", + }, + }, + }, + }, }; internalMappers.SawShark = { required: false, @@ -482,7 +480,7 @@ internalMappers.SawShark = { name: "Composite", polymorphicDiscriminator: { serializedName: "fish.type", - clientName: "fishtype" + clientName: "fishtype", }, uberParent: "Fish", className: "Sawshark", @@ -491,15 +489,15 @@ internalMappers.SawShark = { required: false, serializedName: "species", type: { - name: "String" - } + name: "String", + }, }, length: { required: true, serializedName: "length", type: { - name: "Number" - } + name: "Number", + }, }, siblings: { required: false, @@ -513,44 +511,44 @@ internalMappers.SawShark = { name: "Composite", polymorphicDiscriminator: { serializedName: "fish.type", - clientName: "fishtype" + clientName: "fishtype", }, uberParent: "Fish", - className: "Fish" - } - } - } + className: "Fish", + }, + }, + }, }, fishtype: { required: true, serializedName: "fish\\.type", type: { - name: "String" - } + name: "String", + }, }, age: { required: false, serializedName: "age", type: { - name: "Number" - } + name: "Number", + }, }, birthday: { required: true, serializedName: "birthday", type: { - name: "DateTime" - } + name: "DateTime", + }, }, picture: { required: false, serializedName: "picture", type: { - name: "ByteArray" - } - } - } - } + name: "ByteArray", + }, + }, + }, + }, }; internalMappers.Shark = { required: false, @@ -559,7 +557,7 @@ internalMappers.Shark = { name: "Composite", polymorphicDiscriminator: { serializedName: "fish.type", - clientName: "fishtype" + clientName: "fishtype", }, uberParent: "Fish", className: "Shark", @@ -568,15 +566,15 @@ internalMappers.Shark = { required: false, serializedName: "species", type: { - name: "String" - } + name: "String", + }, }, length: { required: true, serializedName: "length", type: { - name: "Number" - } + name: "Number", + }, }, siblings: { required: false, @@ -590,37 +588,37 @@ internalMappers.Shark = { name: "Composite", polymorphicDiscriminator: { serializedName: "fish.type", - clientName: "fishtype" + clientName: "fishtype", }, uberParent: "Fish", - className: "Fish" - } - } - } + className: "Fish", + }, + }, + }, }, fishtype: { required: true, serializedName: "fish\\.type", type: { - name: "String" - } + name: "String", + }, }, age: { required: false, serializedName: "age", type: { - name: "Number" - } + name: "Number", + }, }, birthday: { required: true, serializedName: "birthday", type: { - name: "DateTime" - } - } - } - } + name: "DateTime", + }, + }, + }, + }, }; internalMappers.SubProduct = { required: false, @@ -633,50 +631,50 @@ internalMappers.SubProduct = { serializedName: "subId", required: true, type: { - name: "Number" - } + name: "Number", + }, }, subName: { serializedName: "subName", required: true, type: { - name: "String" - } + name: "String", + }, }, provisioningState: { serializedName: "provisioningState", required: false, type: { name: "Enum", - allowedValues: ["Creating", "Failed", "Succeeded"] - } + allowedValues: ["Creating", "Failed", "Succeeded"], + }, }, makeTime: { serializedName: "makeTime", required: false, type: { - name: "DateTime" - } + name: "DateTime", + }, }, invoiceInfo: { serializedName: "invoiceInfo", required: false, type: { name: "Composite", - className: "Invoice" - } - } - } - } + className: "Invoice", + }, + }, + }, + }, }; internalMappers.discriminators = { - "Fish": internalMappers.Fish, + Fish: internalMappers.Fish, "Fish.shark": internalMappers.Shark, "Fish.sawshark": internalMappers.SawShark, - "Pet": internalMappers.Pet, + Pet: internalMappers.Pet, "Pet.Cat": internalMappers.Cat, - "Pet.Dog": internalMappers.Dog + "Pet.Dog": internalMappers.Dog, }; export const Mappers = internalMappers; diff --git a/test/defaultHttpClientTests.ts b/test/defaultHttpClientTests.ts index 9625360..d3b7618 100644 --- a/test/defaultHttpClientTests.ts +++ b/test/defaultHttpClientTests.ts @@ -19,7 +19,8 @@ function getAbortController(): AbortController { if (typeof AbortController === "function") { controller = new AbortController(); } else { - const AbortControllerPonyfill = require("abortcontroller-polyfill/dist/cjs-ponyfill").AbortController; + const AbortControllerPonyfill = require("abortcontroller-polyfill/dist/cjs-ponyfill") + .AbortController; controller = new AbortControllerPonyfill(); } return controller; @@ -27,7 +28,7 @@ function getAbortController(): AbortController { describe("defaultHttpClient", function () { function sleep(ms: number): Promise { - return new Promise(resolve => setTimeout(resolve, ms)); + return new Promise((resolve) => setTimeout(resolve, ms)); } let httpMock: HttpMockFacade; @@ -61,7 +62,16 @@ describe("defaultHttpClient", function () { }); const controller = getAbortController(); const veryBigPayload = "very long string"; - const request = new WebResource(resourceUrl, "POST", veryBigPayload, undefined, undefined, true, undefined, controller.signal); + const request = new WebResource( + resourceUrl, + "POST", + veryBigPayload, + undefined, + undefined, + true, + undefined, + controller.signal + ); const client = new DefaultHttpClient(); const promise = client.sendRequest(request); controller.abort(); @@ -78,14 +88,14 @@ describe("defaultHttpClient", function () { httpMock.get("http://my.fake.domain/set-cookie", { status: 200, headers: { - "Set-Cookie": "data=123456" - } + "Set-Cookie": "data=123456", + }, }); httpMock.get("http://my.fake.domain/cookie", async (_url, _method, _body, headers) => { return { status: 200, - headers: headers + headers: headers, }; }); @@ -99,7 +109,9 @@ describe("defaultHttpClient", function () { const response2 = await client.sendRequest(request2); response2.headers.get("Cookie")!.should.equal("data=123456"); - const request3 = new WebResource("http://my.fake.domain/cookie", "GET", undefined, undefined, { Cookie: "data=abcdefg" }); + const request3 = new WebResource("http://my.fake.domain/cookie", "GET", undefined, undefined, { + Cookie: "data=abcdefg", + }); const response3 = await client.sendRequest(request3); response3.headers.get("Cookie")!.should.equal("data=abcdefg"); }); @@ -114,11 +126,29 @@ describe("defaultHttpClient", function () { const controller = getAbortController(); const buf = "Very large string"; const requests = [ - new WebResource("/fileupload", "POST", buf, undefined, undefined, true, undefined, controller.signal), - new WebResource("/fileupload", "POST", buf, undefined, undefined, true, undefined, controller.signal) + new WebResource( + "/fileupload", + "POST", + buf, + undefined, + undefined, + true, + undefined, + controller.signal + ), + new WebResource( + "/fileupload", + "POST", + buf, + undefined, + undefined, + true, + undefined, + controller.signal + ), ]; const client = new DefaultHttpClient(); - const promises = requests.map(r => client.sendRequest(r)); + const promises = requests.map((r) => client.sendRequest(r)); controller.abort(); // Ensure each promise is individually rejected for (const promise of promises) { @@ -143,16 +173,30 @@ describe("defaultHttpClient", function () { it("for simple bodies", async function () { httpMock.post("/fileupload", async (_url, _method, _body) => { - return { status: 251, body: body.repeat(9).substring(0, 200), headers: { "Content-Length": "200" } }; + return { + status: 251, + body: body.repeat(9).substring(0, 200), + headers: { "Content-Length": "200" }, + }; }); const upload: Notified = { notified: false }; const download: Notified = { notified: false }; const body = "Very large string to upload"; - const request = new WebResource("/fileupload", "POST", body, undefined, undefined, false, undefined, undefined, 0, - ev => listener(upload, ev), - ev => listener(download, ev)); + const request = new WebResource( + "/fileupload", + "POST", + body, + undefined, + undefined, + false, + undefined, + undefined, + 0, + (ev) => listener(upload, ev), + (ev) => listener(download, ev) + ); const client = new DefaultHttpClient(); const response = await client.sendRequest(request); @@ -173,24 +217,38 @@ describe("defaultHttpClient", function () { const size = isNode ? payload.toString().length : undefined; httpMock.post("/bigfileupload", async (_url, _method, _body) => { - return { status: 250, body: payload, headers: { "Content-Type": "text/javascript", "Content-length": size } }; + return { + status: 250, + body: payload, + headers: { "Content-Type": "text/javascript", "Content-length": size }, + }; }); const upload: Notified = { notified: false }; const download: Notified = { notified: false }; - const request = new WebResource("/bigfileupload", "POST", payload, undefined, undefined, true, undefined, undefined, 0, - ev => listener(upload, ev), - ev => listener(download, ev)); + const request = new WebResource( + "/bigfileupload", + "POST", + payload, + undefined, + undefined, + true, + undefined, + undefined, + 0, + (ev) => listener(upload, ev), + (ev) => listener(download, ev) + ); const client = new DefaultHttpClient(); const response = await client.sendRequest(request); response.status.should.equal(250); if (response.blobBody) { await response.blobBody; - } else if ((typeof response.readableStreamBody === "function")) { + } else if (typeof response.readableStreamBody === "function") { const streamBody = (response.readableStreamBody as Function)(); - streamBody.on("data", () => { }); + streamBody.on("data", () => {}); await new Promise((resolve, reject) => { streamBody.on("end", resolve); streamBody.on("error", reject); @@ -205,7 +263,17 @@ describe("defaultHttpClient", function () { it("should honor request timeouts", async function () { httpMock.timeout("GET", "/slow"); - const request = new WebResource("/slow", "GET", undefined, undefined, undefined, false, false, undefined, 100); + const request = new WebResource( + "/slow", + "GET", + undefined, + undefined, + undefined, + false, + false, + undefined, + 100 + ); const client = new DefaultHttpClient(); try { await client.sendRequest(request); @@ -234,12 +302,12 @@ describe("defaultHttpClient", function () { httpMock.put(requestUrl, async (_url, _method, body, _headers) => { if (!body) { return { - status: 200 + status: 200, }; } else { return { status: 400, - body: `Expected empty body but got "${JSON.stringify(body)}"` + body: `Expected empty body but got "${JSON.stringify(body)}"`, }; } }); @@ -264,8 +332,7 @@ describe("defaultHttpClient", function () { assert(response.headers); assert.strictEqual(response.headers.get("content-type")!.split(";")[0], "text/html"); const responseBody: string | null | undefined = response.bodyAsText; - const expectedResponseBody = - ` + const expectedResponseBody = ` Example Domain @@ -314,7 +381,8 @@ describe("defaultHttpClient", function () { `; assert.strictEqual( responseBody && responseBody.replace(/\s/g, ""), - expectedResponseBody.replace(/\s/g, "")); + expectedResponseBody.replace(/\s/g, "") + ); httpMock.teardown(); }); }); diff --git a/test/logFilterTests.ts b/test/logFilterTests.ts index c041c2e..31be4a5 100644 --- a/test/logFilterTests.ts +++ b/test/logFilterTests.ts @@ -12,11 +12,10 @@ const emptyRequestPolicy: RequestPolicy = { sendRequest(request: WebResource): Promise { // tslint:disable-next-line: no-null-keyword return Promise.resolve({ request, status: 200, headers: new HttpHeaders(), bodyAsText: null }); - } + }, }; describe("Log filter", () => { - it("should log messages when a logger object is provided", (done) => { const expected = `>> Request: { "url": "https://foo.com", @@ -34,17 +33,21 @@ describe("Log filter", () => { >> Body: null `; let output = ""; - const logger = (message: string): void => { output += message + "\n"; }; + const logger = (message: string): void => { + output += message + "\n"; + }; const lf = new LogPolicy(emptyRequestPolicy, new RequestPolicyOptions(), logger); - const req = new WebResource("https://foo.com", "PUT", { "a": 1 }); - lf.sendRequest(req).then(() => { - // console.dir(output, { depth: null }); - // console.log(">>>>>>>"); - // console.dir(expected); - assert.deepEqual(output, expected); - done(); - }).catch((err: Error) => { - done(err); - }); + const req = new WebResource("https://foo.com", "PUT", { a: 1 }); + lf.sendRequest(req) + .then(() => { + // console.dir(output, { depth: null }); + // console.log(">>>>>>>"); + // console.dir(expected); + assert.deepEqual(output, expected); + done(); + }) + .catch((err: Error) => { + done(err); + }); }); }); diff --git a/test/mockHttp.ts b/test/mockHttp.ts index 75351a2..38ce773 100644 --- a/test/mockHttp.ts +++ b/test/mockHttp.ts @@ -14,7 +14,12 @@ export type MockResponseData = { headers?: any; }; -export type MockResponseFunction = (url?: string, method?: string, body?: any, headers?: any) => Promise; +export type MockResponseFunction = ( + url?: string, + method?: string, + body?: any, + headers?: any +) => Promise; export type MockResponse = MockResponseData | MockResponseFunction; @@ -30,7 +35,7 @@ export interface HttpMockFacade { } export function getHttpMock(): HttpMockFacade { - return (isNode ? new FetchHttpMock() : new BrowserHttpMock()); + return isNode ? new FetchHttpMock() : new BrowserHttpMock(); } class FetchHttpMock implements HttpMockFacade { @@ -48,7 +53,7 @@ class FetchHttpMock implements HttpMockFacade { timeout(_method: HttpMethods, url: UrlFilter): void { const delay = new Promise((resolve) => { - setTimeout(() => resolve({$uri: url, delay: 500}), 2500); + setTimeout(() => resolve({ $uri: url, delay: 500 }), 2500); }); fetchMock.mock(url, delay); @@ -82,7 +87,8 @@ class FetchHttpMock implements HttpMockFacade { }) as fetch.MockResponseFunction; } - const matcher = (_url: string, opts: fetch.MockRequest) => (url === _url) && (opts.method === method); + const matcher = (_url: string, opts: fetch.MockRequest) => + url === _url && opts.method === method; fetchMock.mock(matcher, mockResponse); } @@ -111,13 +117,21 @@ export class BrowserHttpMock implements HttpMockFacade { mockHttpMethod(method: HttpMethods, url: UrlFilter, response: MockResponse): void { if (typeof response === "function") { xhrMock.use(method, url, async (req, res) => { - const result = await response(req.url().toString(), req.method().toString(), req.body(), req.headers()); - return res.status(result.status || 200).body(result.body || {}).headers(result.headers || {}); + const result = await response( + req.url().toString(), + req.method().toString(), + req.body(), + req.headers() + ); + return res + .status(result.status || 200) + .body(result.body || {}) + .headers(result.headers || {}); }); } else { xhrMock.use(method, url, { status: response.status, - body: response.body + body: response.body, }); } } @@ -143,7 +157,6 @@ export class BrowserHttpMock implements HttpMockFacade { } timeout(method: HttpMethods, url: UrlFilter): void { - return this.mockHttpMethod(method, url, () => new Promise(() => { })); + return this.mockHttpMethod(method, url, () => new Promise(() => {})); } } - diff --git a/test/msAssert.ts b/test/msAssert.ts index b9dfe34..e8d3fb8 100644 --- a/test/msAssert.ts +++ b/test/msAssert.ts @@ -5,10 +5,14 @@ import { assert } from "chai"; import { SuiteFunction, PendingSuiteFunction, TestFunction, PendingTestFunction } from "mocha"; import { isNode } from "../lib/util/utils"; -export const nodeIt: TestFunction | PendingTestFunction = (!isNode ? it.skip : it); -export const browserIt: TestFunction | PendingTestFunction = (isNode ? it.skip : it); -export const nodeDescribe: SuiteFunction | PendingSuiteFunction = (!isNode ? describe.skip : describe); -export const browserDescribe: SuiteFunction | PendingSuiteFunction = (isNode ? describe.skip : describe); +export const nodeIt: TestFunction | PendingTestFunction = !isNode ? it.skip : it; +export const browserIt: TestFunction | PendingTestFunction = isNode ? it.skip : it; +export const nodeDescribe: SuiteFunction | PendingSuiteFunction = !isNode + ? describe.skip + : describe; +export const browserDescribe: SuiteFunction | PendingSuiteFunction = isNode + ? describe.skip + : describe; /** * Assert that the provided syncFunction throws an Error. If the expectedError is undefined, then @@ -17,7 +21,10 @@ export const browserDescribe: SuiteFunction | PendingSuiteFunction = (isNode ? d * @param syncFunction The synchronous function that is expected to thrown an Error. * @param expectedError The Error that is expected to be thrown. */ -export function throws(syncFunction: () => void, expectedError?: ((error: Error) => void) | Error): Error { +export function throws( + syncFunction: () => void, + expectedError?: ((error: Error) => void) | Error +): Error { let thrownError: Error | undefined; try { @@ -27,7 +34,7 @@ export function throws(syncFunction: () => void, expectedError?: ((error: Error) } if (!thrownError) { - assert.throws(() => { }); + assert.throws(() => {}); } else if (expectedError instanceof Error) { assert.deepEqual(thrownError, expectedError); } else if (expectedError) { @@ -44,7 +51,10 @@ export function throws(syncFunction: () => void, expectedError?: ((error: Error) * @param asyncFunction The asynchronous function that is expected to thrown an Error. * @param expectedError The Error that is expected to be thrown. */ -export async function throwsAsync(asyncFunction: (() => Promise) | Promise, expectedError?: ((error: Error) => void) | Error): Promise { +export async function throwsAsync( + asyncFunction: (() => Promise) | Promise, + expectedError?: ((error: Error) => void) | Error +): Promise { let thrownError: Error | undefined; try { @@ -54,7 +64,7 @@ export async function throwsAsync(asyncFunction: (() => Promise) | Promise } if (!thrownError) { - assert.throws(() => { }); + assert.throws(() => {}); } else if (expectedError instanceof Error) { assert.deepEqual(thrownError, expectedError); } else if (expectedError) { diff --git a/test/msRestUserAgentPolicyTests.ts b/test/msRestUserAgentPolicyTests.ts index d9f1bfc..d9ffe94 100644 --- a/test/msRestUserAgentPolicyTests.ts +++ b/test/msRestUserAgentPolicyTests.ts @@ -16,7 +16,7 @@ const emptyRequestPolicy: RequestPolicy = { sendRequest(request: WebResource): Promise { request.should.exist; return Promise.resolve({ request: request, status: 200, headers: request.headers }); - } + }, }; const getPlainUserAgentPolicy = (headerValue?: string): RequestPolicy => { @@ -96,18 +96,18 @@ describe("MsRestUserAgentPolicy", () => { }); }); - browserDescribe("for browser", function() { + browserDescribe("for browser", function () { const userAgentHeaderKey = "x-ms-command-name"; const emptyRequestPolicy: RequestPolicy = { sendRequest(request: WebResource): Promise { request.should.exist; return Promise.resolve({ request: request, status: 200, headers: request.headers }); - } + }, }; const getUserAgent = async (headerValue?: string): Promise => { - const factory = userAgentPolicy({ value: headerValue}); + const factory = userAgentPolicy({ value: headerValue }); const policy = factory.create(emptyRequestPolicy, new RequestPolicyOptions()); const resource = new WebResource(); await policy.sendRequest(resource); @@ -118,7 +118,10 @@ describe("MsRestUserAgentPolicy", () => { describe("MsRestUserAgentPolicy (Browser)", () => { it("should not modify user agent header if already present", async () => { const factory = userAgentPolicy(); - const browserUserAgentPolicy = factory.create(emptyRequestPolicy, new RequestPolicyOptions()); + const browserUserAgentPolicy = factory.create( + emptyRequestPolicy, + new RequestPolicyOptions() + ); const customUserAgent = "my custom user agent"; const resource = new WebResource(); resource.headers.set(userAgentHeaderKey, customUserAgent); @@ -132,7 +135,10 @@ describe("MsRestUserAgentPolicy", () => { it("should use injected user agent string if provided", async () => { const customUserAgent = "my custom user agent"; const factory = userAgentPolicy({ value: customUserAgent }); - const browserUserAgentPolicy = factory.create(emptyRequestPolicy, new RequestPolicyOptions()); + const browserUserAgentPolicy = factory.create( + emptyRequestPolicy, + new RequestPolicyOptions() + ); const resource = new WebResource(); await browserUserAgentPolicy.sendRequest(resource); diff --git a/test/operationParameterTests.ts b/test/operationParameterTests.ts index 8937d53..8555cd0 100644 --- a/test/operationParameterTests.ts +++ b/test/operationParameterTests.ts @@ -20,9 +20,9 @@ describe("getParameterPathString()", () => { mapper: { serializedName: "value", type: { - name: "Number" - } - } + name: "Number", + }, + }, }; assert.strictEqual(getPathStringFromParameter(parameter), "pathToParameterValue"); }); @@ -33,9 +33,9 @@ describe("getParameterPathString()", () => { mapper: { serializedName: "value", type: { - name: "Number" - } - } + name: "Number", + }, + }, }; assert.strictEqual(getPathStringFromParameter(parameter), "path.to.parameter.value"); }); @@ -46,9 +46,9 @@ describe("getParameterPathString()", () => { mapper: { serializedName: "value", type: { - name: "Number" - } - } + name: "Number", + }, + }, }; assert.strictEqual(getPathStringFromParameter(parameter), "pa.th.to.par.ameter.valu.e"); }); @@ -56,15 +56,15 @@ describe("getParameterPathString()", () => { it("should return the mapper's serialized name when the parameterPath is an object", () => { const parameter: OperationParameter = { parameterPath: { - "a": "A", - "b": "B" + a: "A", + b: "B", }, mapper: { serializedName: "value", type: { - name: "Number" - } - } + name: "Number", + }, + }, }; assert.strictEqual(getPathStringFromParameter(parameter), "value"); }); diff --git a/test/policies/agentPolicyTests.ts b/test/policies/agentPolicyTests.ts index 093608d..4789d83 100644 --- a/test/policies/agentPolicyTests.ts +++ b/test/policies/agentPolicyTests.ts @@ -33,30 +33,19 @@ describe("AgentPolicy", function () { it("factory passes correct agent settings", function () { const factory = agentPolicy(agentSettings); - const policy = factory.create( - emptyRequestPolicy, - emptyPolicyOptions - ) as AgentPolicy; + const policy = factory.create(emptyRequestPolicy, emptyPolicyOptions) as AgentPolicy; policy.agentSettings.should.be.deep.equal(agentSettings); }); it("sets correct agent settings through constructor", function () { - const policy = new AgentPolicy( - emptyRequestPolicy, - emptyPolicyOptions, - agentSettings - ); + const policy = new AgentPolicy(emptyRequestPolicy, emptyPolicyOptions, agentSettings); policy.agentSettings.should.be.deep.equal(agentSettings); }); it("should assign agent settings to the web request", async function () { - const policy = new AgentPolicy( - emptyRequestPolicy, - emptyPolicyOptions, - agentSettings - ); + const policy = new AgentPolicy(emptyRequestPolicy, emptyPolicyOptions, agentSettings); const request = new WebResource(); await policy.sendRequest(request); @@ -65,16 +54,12 @@ describe("AgentPolicy", function () { }); it("should not override agent settings to the web request", async function () { - const policy = new AgentPolicy( - emptyRequestPolicy, - emptyPolicyOptions, - agentSettings - ); + const policy = new AgentPolicy(emptyRequestPolicy, emptyPolicyOptions, agentSettings); const request = new WebResource(); const requestSpecificAgentSettings = { - http: new http.Agent({keepAlive: true}), - https: new http.Agent({keepAlive: true}), + http: new http.Agent({ keepAlive: true }), + https: new http.Agent({ keepAlive: true }), }; request.agentSettings = requestSpecificAgentSettings; diff --git a/test/policies/deserializationPolicyTests.ts b/test/policies/deserializationPolicyTests.ts index ef3b241..f0d5c15 100644 --- a/test/policies/deserializationPolicyTests.ts +++ b/test/policies/deserializationPolicyTests.ts @@ -5,7 +5,13 @@ import { assert } from "chai"; import { HttpHeaders } from "../../lib/httpHeaders"; import { HttpOperationResponse } from "../../lib/httpOperationResponse"; import { HttpClient, OperationSpec, Serializer } from "../../lib/msRest"; -import { DeserializationPolicy, deserializationPolicy, deserializeResponseBody, defaultJsonContentTypes, defaultXmlContentTypes } from "../../lib/policies/deserializationPolicy"; +import { + DeserializationPolicy, + deserializationPolicy, + deserializeResponseBody, + defaultJsonContentTypes, + defaultXmlContentTypes, +} from "../../lib/policies/deserializationPolicy"; import { RequestPolicy, RequestPolicyOptions } from "../../lib/policies/requestPolicy"; import { WebResource, WebResourceLike } from "../../lib/webResource"; @@ -15,13 +21,17 @@ describe("deserializationPolicy", function () { return Promise.resolve({ request: request, status: 200, - headers: new HttpHeaders() + headers: new HttpHeaders(), }); - } + }, }; it(`should not modify a request that has no request body mapper`, async function () { - const deserializationPolicy = new DeserializationPolicy(mockPolicy, {}, new RequestPolicyOptions()); + const deserializationPolicy = new DeserializationPolicy( + mockPolicy, + {}, + new RequestPolicyOptions() + ); const request = createRequest(); request.body = "hello there!"; @@ -33,12 +43,13 @@ describe("deserializationPolicy", function () { it("should parse a JSON response body", async function () { const request: WebResourceLike = createRequest(); const mockClient: HttpClient = { - sendRequest: req => Promise.resolve({ - request: req, - status: 200, - headers: new HttpHeaders({ "Content-Type": "application/json" }), - bodyAsText: "[123, 456, 789]" - }) + sendRequest: (req) => + Promise.resolve({ + request: req, + status: 200, + headers: new HttpHeaders({ "Content-Type": "application/json" }), + bodyAsText: "[123, 456, 789]", + }), }; const policy = deserializationPolicy().create(mockClient, new RequestPolicyOptions()); @@ -49,12 +60,13 @@ describe("deserializationPolicy", function () { it("should parse a JSON response body with a charset specified in Content-Type", async function () { const request: WebResourceLike = createRequest(); const mockClient: HttpClient = { - sendRequest: req => Promise.resolve({ - request: req, - status: 200, - headers: new HttpHeaders({ "Content-Type": "application/json;charset=UTF-8" }), - bodyAsText: "[123, 456, 789]" - }) + sendRequest: (req) => + Promise.resolve({ + request: req, + status: 200, + headers: new HttpHeaders({ "Content-Type": "application/json;charset=UTF-8" }), + bodyAsText: "[123, 456, 789]", + }), }; const policy = deserializationPolicy().create(mockClient, new RequestPolicyOptions()); @@ -65,12 +77,13 @@ describe("deserializationPolicy", function () { it("should parse a JSON response body with an uppercase Content-Type", async function () { const request: WebResourceLike = createRequest(); const mockClient: HttpClient = { - sendRequest: req => Promise.resolve({ - request: req, - status: 200, - headers: new HttpHeaders({ "Content-Type": "APPLICATION/JSON" }), - bodyAsText: "[123, 456, 789]" - }) + sendRequest: (req) => + Promise.resolve({ + request: req, + status: 200, + headers: new HttpHeaders({ "Content-Type": "APPLICATION/JSON" }), + bodyAsText: "[123, 456, 789]", + }), }; const policy = deserializationPolicy().create(mockClient, new RequestPolicyOptions()); @@ -81,12 +94,13 @@ describe("deserializationPolicy", function () { it("should parse a JSON response body with a missing Content-Type", async function () { const request: WebResourceLike = createRequest(); const mockClient: HttpClient = { - sendRequest: req => Promise.resolve({ - request: req, - status: 200, - headers: new HttpHeaders(), - bodyAsText: "[123, 456, 789]" - }) + sendRequest: (req) => + Promise.resolve({ + request: req, + status: 200, + headers: new HttpHeaders(), + bodyAsText: "[123, 456, 789]", + }), }; const policy = deserializationPolicy().create(mockClient, new RequestPolicyOptions()); @@ -99,7 +113,7 @@ describe("deserializationPolicy", function () { const response: HttpOperationResponse = { request: createRequest(), status: 200, - headers: new HttpHeaders() + headers: new HttpHeaders(), }; const deserializedResponse: HttpOperationResponse = await deserializeResponse(response); @@ -117,9 +131,9 @@ describe("deserializationPolicy", function () { request: createRequest(), status: 200, headers: new HttpHeaders({ - "content-type": "application/xml" + "content-type": "application/xml", }), - bodyAsText: `3` + bodyAsText: `3`, }; const deserializedResponse: HttpOperationResponse = await deserializeResponse(response); @@ -128,7 +142,7 @@ describe("deserializationPolicy", function () { assert.strictEqual(deserializedResponse.readableStreamBody, undefined); assert.strictEqual(deserializedResponse.blobBody, undefined); assert.strictEqual(deserializedResponse.bodyAsText, `3`); - assert.deepEqual(deserializedResponse.parsedBody, { "apples": "3" }); + assert.deepEqual(deserializedResponse.parsedBody, { apples: "3" }); assert.strictEqual(deserializedResponse.parsedHeaders, undefined); }); @@ -137,9 +151,9 @@ describe("deserializationPolicy", function () { request: createRequest(), status: 200, headers: new HttpHeaders({ - "content-type": "application/xml" + "content-type": "application/xml", }), - bodyAsText: `3` + bodyAsText: `3`, }; const deserializedResponse: HttpOperationResponse = await deserializeResponse(response); @@ -147,14 +161,17 @@ describe("deserializationPolicy", function () { assert(deserializedResponse); assert.strictEqual(deserializedResponse.readableStreamBody, undefined); assert.strictEqual(deserializedResponse.blobBody, undefined); - assert.strictEqual(deserializedResponse.bodyAsText, `3`); + assert.strictEqual( + deserializedResponse.bodyAsText, + `3` + ); assert.deepEqual(deserializedResponse.parsedBody, { - "apples": { - "$": { - "tasty": "yes" + apples: { + $: { + tasty: "yes", }, - "_": "3" - } + _: "3", + }, }); assert.strictEqual(deserializedResponse.parsedHeaders, undefined); }); @@ -177,20 +194,20 @@ describe("deserializationPolicy", function () { xmlName: "apples", serializedName: "apples", type: { - name: "String" - } - } - } - } - } - } - } + name: "String", + }, + }, + }, + }, + }, + }, + }, }), status: 200, headers: new HttpHeaders({ - "content-type": "application/xml" + "content-type": "application/xml", }), - bodyAsText: `3` + bodyAsText: `3`, }; const deserializedResponse: HttpOperationResponse = await deserializeResponse(response); @@ -198,8 +215,11 @@ describe("deserializationPolicy", function () { assert(deserializedResponse); assert.strictEqual(deserializedResponse.readableStreamBody, undefined); assert.strictEqual(deserializedResponse.blobBody, undefined); - assert.strictEqual(deserializedResponse.bodyAsText, `3`); - assert.deepEqual(deserializedResponse.parsedBody, { "apples": "3" }); + assert.strictEqual( + deserializedResponse.bodyAsText, + `3` + ); + assert.deepEqual(deserializedResponse.parsedBody, { apples: "3" }); assert.strictEqual(deserializedResponse.parsedHeaders, undefined); }); @@ -221,20 +241,20 @@ describe("deserializationPolicy", function () { xmlName: "apples", serializedName: "apples", type: { - name: "Number" - } - } - } - } - } - } - } + name: "Number", + }, + }, + }, + }, + }, + }, + }, }), status: 200, headers: new HttpHeaders({ - "content-type": "application/xml" + "content-type": "application/xml", }), - bodyAsText: `3` + bodyAsText: `3`, }; const deserializedResponse: HttpOperationResponse = await deserializeResponse(response); @@ -242,8 +262,11 @@ describe("deserializationPolicy", function () { assert(deserializedResponse); assert.strictEqual(deserializedResponse.readableStreamBody, undefined); assert.strictEqual(deserializedResponse.blobBody, undefined); - assert.strictEqual(deserializedResponse.bodyAsText, `3`); - assert.deepEqual(deserializedResponse.parsedBody, { "apples": 3 }); + assert.strictEqual( + deserializedResponse.bodyAsText, + `3` + ); + assert.deepEqual(deserializedResponse.parsedBody, { apples: 3 }); assert.strictEqual(deserializedResponse.parsedHeaders, undefined); }); @@ -273,23 +296,23 @@ describe("deserializationPolicy", function () { xmlIsAttribute: true, serializedName: "tasty", type: { - name: "String" - } - } - } - } - } - } - } - } - } - } + name: "String", + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, }), status: 200, headers: new HttpHeaders({ - "content-type": "application/xml" + "content-type": "application/xml", }), - bodyAsText: `3` + bodyAsText: `3`, }; const deserializedResponse: HttpOperationResponse = await deserializeResponse(response); @@ -297,8 +320,11 @@ describe("deserializationPolicy", function () { assert(deserializedResponse); assert.strictEqual(deserializedResponse.readableStreamBody, undefined); assert.strictEqual(deserializedResponse.blobBody, undefined); - assert.strictEqual(deserializedResponse.bodyAsText, `3`); - assert.deepEqual(deserializedResponse.parsedBody, { "apples": { "tasty": "yes" } }); + assert.strictEqual( + deserializedResponse.bodyAsText, + `3` + ); + assert.deepEqual(deserializedResponse.parsedBody, { apples: { tasty: "yes" } }); assert.strictEqual(deserializedResponse.parsedHeaders, undefined); }); @@ -307,9 +333,9 @@ describe("deserializationPolicy", function () { request: createRequest(), status: 200, headers: new HttpHeaders({ - "content-type": "application/atom+xml" + "content-type": "application/atom+xml", }), - bodyAsText: `3` + bodyAsText: `3`, }; const deserializedResponse: HttpOperationResponse = await deserializeResponse(response); @@ -318,7 +344,7 @@ describe("deserializationPolicy", function () { assert.strictEqual(deserializedResponse.readableStreamBody, undefined); assert.strictEqual(deserializedResponse.blobBody, undefined); assert.strictEqual(deserializedResponse.bodyAsText, `3`); - assert.deepEqual(deserializedResponse.parsedBody, { "apples": "3" }); + assert.deepEqual(deserializedResponse.parsedBody, { apples: "3" }); assert.strictEqual(deserializedResponse.parsedHeaders, undefined); }); @@ -327,9 +353,9 @@ describe("deserializationPolicy", function () { request: createRequest(), status: 200, headers: new HttpHeaders({ - "content-type": "application/atom+xml" + "content-type": "application/atom+xml", }), - bodyAsText: `3` + bodyAsText: `3`, }; const deserializedResponse: HttpOperationResponse = await deserializeResponse(response); @@ -337,14 +363,17 @@ describe("deserializationPolicy", function () { assert(deserializedResponse); assert.strictEqual(deserializedResponse.readableStreamBody, undefined); assert.strictEqual(deserializedResponse.blobBody, undefined); - assert.strictEqual(deserializedResponse.bodyAsText, `3`); + assert.strictEqual( + deserializedResponse.bodyAsText, + `3` + ); assert.deepEqual(deserializedResponse.parsedBody, { - "apples": { - "$": { - "taste": "good" + apples: { + $: { + taste: "good", }, - "_": "3" - } + _: "3", + }, }); assert.strictEqual(deserializedResponse.parsedHeaders, undefined); }); @@ -354,24 +383,31 @@ describe("deserializationPolicy", function () { request: createRequest(), status: 200, headers: new HttpHeaders({ - "content-type": "my/weird-xml" + "content-type": "my/weird-xml", }), - bodyAsText: `3` + bodyAsText: `3`, }; - const deserializedResponse: HttpOperationResponse = await deserializeResponseBody([], ["my/weird-xml"], response); + const deserializedResponse: HttpOperationResponse = await deserializeResponseBody( + [], + ["my/weird-xml"], + response + ); assert(deserializedResponse); assert.strictEqual(deserializedResponse.readableStreamBody, undefined); assert.strictEqual(deserializedResponse.blobBody, undefined); - assert.strictEqual(deserializedResponse.bodyAsText, `3`); + assert.strictEqual( + deserializedResponse.bodyAsText, + `3` + ); assert.deepEqual(deserializedResponse.parsedBody, { - "apples": { - "$": { - "taste": "good" + apples: { + $: { + taste: "good", }, - "_": "3" - } + _: "3", + }, }); assert.strictEqual(deserializedResponse.parsedHeaders, undefined); }); @@ -381,9 +417,9 @@ describe("deserializationPolicy", function () { request: createRequest(), status: 200, headers: new HttpHeaders({ - "content-type": "application/atom+xml;type=entry;charset=utf-8" + "content-type": "application/atom+xml;type=entry;charset=utf-8", }), - bodyAsText: `https://daschulttest1.servicebus.windows.net/testQueuePath/?api-version=2017-04&enrich=FalsetestQueuePath2018-10-09T19:56:34Z2018-10-09T19:56:35Zdaschulttest1PT1M1024falsefalseP14DfalsePT10M10true00falseActive2018-10-09T19:56:34.903Z2018-10-09T19:56:35.013Z0001-01-01T00:00:00Ztrue00000P10675199DT2H48M5.4775807SfalseAvailablefalse` + bodyAsText: `https://daschulttest1.servicebus.windows.net/testQueuePath/?api-version=2017-04&enrich=FalsetestQueuePath2018-10-09T19:56:34Z2018-10-09T19:56:35Zdaschulttest1PT1M1024falsefalseP14DfalsePT10M10true00falseActive2018-10-09T19:56:34.903Z2018-10-09T19:56:35.013Z0001-01-01T00:00:00Ztrue00000P10675199DT2H48M5.4775807SfalseAvailablefalse`, }; const deserializedResponse: HttpOperationResponse = await deserializeResponse(response); @@ -391,72 +427,77 @@ describe("deserializationPolicy", function () { assert(deserializedResponse); assert.strictEqual(deserializedResponse.readableStreamBody, undefined); assert.strictEqual(deserializedResponse.blobBody, undefined); - assert.strictEqual(deserializedResponse.bodyAsText, `https://daschulttest1.servicebus.windows.net/testQueuePath/?api-version=2017-04&enrich=FalsetestQueuePath2018-10-09T19:56:34Z2018-10-09T19:56:35Zdaschulttest1PT1M1024falsefalseP14DfalsePT10M10true00falseActive2018-10-09T19:56:34.903Z2018-10-09T19:56:35.013Z0001-01-01T00:00:00Ztrue00000P10675199DT2H48M5.4775807SfalseAvailablefalse`); + assert.strictEqual( + deserializedResponse.bodyAsText, + `https://daschulttest1.servicebus.windows.net/testQueuePath/?api-version=2017-04&enrich=FalsetestQueuePath2018-10-09T19:56:34Z2018-10-09T19:56:35Zdaschulttest1PT1M1024falsefalseP14DfalsePT10M10true00falseActive2018-10-09T19:56:34.903Z2018-10-09T19:56:35.013Z0001-01-01T00:00:00Ztrue00000P10675199DT2H48M5.4775807SfalseAvailablefalse` + ); assert.deepEqual(deserializedResponse.parsedBody, { - "$": { - "xmlns": "http://www.w3.org/2005/Atom" + $: { + xmlns: "http://www.w3.org/2005/Atom", }, - "author": { - "name": "daschulttest1" + author: { + name: "daschulttest1", }, - "content": { - "$": { - "type": "application/xml" + content: { + $: { + type: "application/xml", }, - "QueueDescription": { - "$": { - "xmlns": "http://schemas.microsoft.com/netservices/2010/10/servicebus/connect", - "xmlns:i": "http://www.w3.org/2001/XMLSchema-instance" + QueueDescription: { + $: { + xmlns: "http://schemas.microsoft.com/netservices/2010/10/servicebus/connect", + "xmlns:i": "http://www.w3.org/2001/XMLSchema-instance", }, - "AccessedAt": "0001-01-01T00:00:00Z", - "AuthorizationRules": "", - "AutoDeleteOnIdle": "P10675199DT2H48M5.4775807S", - "CountDetails": { - "$": { - "xmlns:d2p1": "http://schemas.microsoft.com/netservices/2011/06/servicebus" + AccessedAt: "0001-01-01T00:00:00Z", + AuthorizationRules: "", + AutoDeleteOnIdle: "P10675199DT2H48M5.4775807S", + CountDetails: { + $: { + "xmlns:d2p1": "http://schemas.microsoft.com/netservices/2011/06/servicebus", }, "d2p1:ActiveMessageCount": "0", "d2p1:DeadLetterMessageCount": "0", "d2p1:ScheduledMessageCount": "0", "d2p1:TransferDeadLetterMessageCount": "0", - "d2p1:TransferMessageCount": "0" + "d2p1:TransferMessageCount": "0", }, - "CreatedAt": "2018-10-09T19:56:34.903Z", - "DeadLetteringOnMessageExpiration": "false", - "DefaultMessageTimeToLive": "P14D", - "DuplicateDetectionHistoryTimeWindow": "PT10M", - "EnableBatchedOperations": "true", - "EnableExpress": "false", - "EnablePartitioning": "false", - "EntityAvailabilityStatus": "Available", - "IsAnonymousAccessible": "false", - "LockDuration": "PT1M", - "MaxDeliveryCount": "10", - "MaxSizeInMegabytes": "1024", - "MessageCount": "0", - "RequiresDuplicateDetection": "false", - "RequiresSession": "false", - "SizeInBytes": "0", - "Status": "Active", - "SupportOrdering": "true", - "UpdatedAt": "2018-10-09T19:56:35.013Z" - } - }, - "id": "https://daschulttest1.servicebus.windows.net/testQueuePath/?api-version=2017-04&enrich=False", - "link": { - "$": { - "href": "https://daschulttest1.servicebus.windows.net/testQueuePath/?api-version=2017-04&enrich=False", - "rel": "self" - } - }, - "published": "2018-10-09T19:56:34Z", - "title": { - "$": { - "type": "text" + CreatedAt: "2018-10-09T19:56:34.903Z", + DeadLetteringOnMessageExpiration: "false", + DefaultMessageTimeToLive: "P14D", + DuplicateDetectionHistoryTimeWindow: "PT10M", + EnableBatchedOperations: "true", + EnableExpress: "false", + EnablePartitioning: "false", + EntityAvailabilityStatus: "Available", + IsAnonymousAccessible: "false", + LockDuration: "PT1M", + MaxDeliveryCount: "10", + MaxSizeInMegabytes: "1024", + MessageCount: "0", + RequiresDuplicateDetection: "false", + RequiresSession: "false", + SizeInBytes: "0", + Status: "Active", + SupportOrdering: "true", + UpdatedAt: "2018-10-09T19:56:35.013Z", }, - "_": "testQueuePath" }, - "updated": "2018-10-09T19:56:35Z" + id: + "https://daschulttest1.servicebus.windows.net/testQueuePath/?api-version=2017-04&enrich=False", + link: { + $: { + href: + "https://daschulttest1.servicebus.windows.net/testQueuePath/?api-version=2017-04&enrich=False", + rel: "self", + }, + }, + published: "2018-10-09T19:56:34Z", + title: { + $: { + type: "text", + }, + _: "testQueuePath", + }, + updated: "2018-10-09T19:56:35Z", }); assert.strictEqual(deserializedResponse.parsedHeaders, undefined); }); diff --git a/test/policies/proxyPolicyTests.ts b/test/policies/proxyPolicyTests.ts index 0b17af7..8b23c87 100644 --- a/test/policies/proxyPolicyTests.ts +++ b/test/policies/proxyPolicyTests.ts @@ -16,15 +16,16 @@ describe("ProxyPolicy", function () { host: "https://example.com", port: 3030, username: "admin", - password: "_password" + password: "_password", }; const emptyRequestPolicy = { - sendRequest: (_: WebResourceLike) => Promise.resolve({ - request: new WebResource(), - status: 404, - headers: new HttpHeaders(undefined) - }) + sendRequest: (_: WebResourceLike) => + Promise.resolve({ + request: new WebResource(), + status: 404, + headers: new HttpHeaders(undefined), + }), }; const emptyPolicyOptions = new RequestPolicyOptions(); @@ -38,7 +39,6 @@ describe("ProxyPolicy", function () { done(); }); - it("sets correct proxy settings through constructor", function (done) { const policy = new ProxyPolicy(emptyRequestPolicy, emptyPolicyOptions, proxySettings); policy.proxySettings.should.be.deep.equal(proxySettings); @@ -68,7 +68,8 @@ describe("ProxyPolicy", function () { browserDescribe("for browser", () => { it("should throw an Error while constructing object", () => { - const construct = () => new ProxyPolicy(emptyRequestPolicy, emptyPolicyOptions, proxySettings); + const construct = () => + new ProxyPolicy(emptyRequestPolicy, emptyPolicyOptions, proxySettings); construct.should.throw(); }); }); @@ -122,9 +123,9 @@ describe("getDefaultProxySettings", () => { describe("should prefer HTTPS proxy over HTTP proxy", () => { [ - { name: "lower case", func: (envVar: string) => envVar.toLowerCase() }, - { name: "upper case", func: (envVar: string) => envVar.toUpperCase() } - ].forEach(testCase => { + { name: "lower case", func: (envVar: string) => envVar.toLowerCase() }, + { name: "upper case", func: (envVar: string) => envVar.toUpperCase() }, + ].forEach((testCase) => { it(`with ${testCase.name}`, () => { const httpProxy = "http://proxy.microsoft.com"; const httpsProxy = "https://proxy.azure.com"; @@ -149,7 +150,7 @@ describe("getDefaultProxySettings", () => { }); }); - ["HTTP_PROXY", "HTTPS_PROXY", "http_proxy", "https_proxy"].forEach(envVariableName => { + ["HTTP_PROXY", "HTTPS_PROXY", "http_proxy", "https_proxy"].forEach((envVariableName) => { it(`should should load setting from "${envVariableName}" environmental variable`, () => { process.env[envVariableName] = proxyUrl; const proxySettings: ProxySettings = getDefaultProxySettings()!; @@ -162,11 +163,13 @@ describe("getDefaultProxySettings", () => { }); browserDescribe("for browser", () => { - [undefined, "http://proxy.microsoft.com", "https://proxy.azure.com:8080"].forEach(proxyUrl => { - it(`should return undefined for ${proxyUrl}`, () => { - const proxySettings = getDefaultProxySettings(proxyUrl); - should().not.exist(proxySettings); - }); - }); + [undefined, "http://proxy.microsoft.com", "https://proxy.azure.com:8080"].forEach( + (proxyUrl) => { + it(`should return undefined for ${proxyUrl}`, () => { + const proxySettings = getDefaultProxySettings(proxyUrl); + should().not.exist(proxySettings); + }); + } + ); }); }); diff --git a/test/policies/throttlingRetryPolicyTests.ts b/test/policies/throttlingRetryPolicyTests.ts index 3d51a81..e91b12c 100644 --- a/test/policies/throttlingRetryPolicyTests.ts +++ b/test/policies/throttlingRetryPolicyTests.ts @@ -10,11 +10,11 @@ import { HttpHeaders, RequestPolicyOptions } from "../../lib/msRest"; describe("ThrottlingRetryPolicy", () => { class PassThroughPolicy { - constructor(private _response: HttpOperationResponse) { } + constructor(private _response: HttpOperationResponse) {} public sendRequest(request: WebResourceLike): Promise { const response = { ...this._response, - request: request + request: request, }; return Promise.resolve(response); @@ -24,10 +24,16 @@ describe("ThrottlingRetryPolicy", () => { const defaultResponse = { status: 200, request: new WebResource(), - headers: new HttpHeaders() + headers: new HttpHeaders(), }; - function createDefaultThrottlingRetryPolicy(response?: HttpOperationResponse, actionHandler?: (httpRequest: WebResourceLike, response: HttpOperationResponse) => Promise) { + function createDefaultThrottlingRetryPolicy( + response?: HttpOperationResponse, + actionHandler?: ( + httpRequest: WebResourceLike, + response: HttpOperationResponse + ) => Promise + ) { if (!response) { response = defaultResponse; } @@ -43,7 +49,7 @@ describe("ThrottlingRetryPolicy", () => { sendRequest: (requestToSend: WebResourceLike): Promise => { assert(request !== requestToSend); return Promise.resolve(defaultResponse); - } + }, }; const policy = new ThrottlingRetryPolicy(nextPolicy, new RequestPolicyOptions()); await policy.sendRequest(request); @@ -54,7 +60,7 @@ describe("ThrottlingRetryPolicy", () => { request.url = "http://url"; request.method = "PATCH"; request.body = { someProperty: "someValue" }; - request.headers = new HttpHeaders({ "header": "abc" }); + request.headers = new HttpHeaders({ header: "abc" }); request.query = { q: "param" }; const policy = createDefaultThrottlingRetryPolicy(); @@ -68,11 +74,13 @@ describe("ThrottlingRetryPolicy", () => { const mockResponse = { status: 400, headers: new HttpHeaders({ - "Retry-After": "100" + "Retry-After": "100", }), - request: request + request: request, }; - const policy = createDefaultThrottlingRetryPolicy(mockResponse, _ => { throw new AssertionError("fail"); }); + const policy = createDefaultThrottlingRetryPolicy(mockResponse, (_) => { + throw new AssertionError("fail"); + }); const response = await policy.sendRequest(request); @@ -84,9 +92,9 @@ describe("ThrottlingRetryPolicy", () => { const mockResponse = { status: 429, headers: new HttpHeaders({ - "Retry-After": "100" + "Retry-After": "100", }), - request: request + request: request, }; const policy = createDefaultThrottlingRetryPolicy(mockResponse, (_, response) => { assert.deepEqual(response, mockResponse); @@ -112,7 +120,9 @@ describe("ThrottlingRetryPolicy", () => { it("should return sleep interval value in milliseconds for full date format", function (done) { const clock = sinon.useFakeTimers(new Date("Fri, 31 Dec 1999 23:00:00 GMT").getTime()); - const retryAfter = ThrottlingRetryPolicy.parseRetryAfterHeader("Fri, 31 Dec 1999 23:02:00 GMT"); + const retryAfter = ThrottlingRetryPolicy.parseRetryAfterHeader( + "Fri, 31 Dec 1999 23:02:00 GMT" + ); assert.equal(retryAfter, 2 * 60 * 1000); diff --git a/test/proxyAgent.node.ts b/test/proxyAgent.node.ts index 86b619f..3622eec 100644 --- a/test/proxyAgent.node.ts +++ b/test/proxyAgent.node.ts @@ -12,11 +12,11 @@ import { createProxyAgent, createTunnel } from "../lib/proxyAgent"; describe("proxyAgent", () => { describe("createProxyAgent", () => { type HttpsAgent = https.Agent & { - defaultPort: number | undefined, + defaultPort: number | undefined; options: { - proxy: tunnel.ProxyOptions - }, - proxyOptions: tunnel.ProxyOptions + proxy: tunnel.ProxyOptions; + }; + proxyOptions: tunnel.ProxyOptions; }; [ @@ -24,13 +24,15 @@ describe("proxyAgent", () => { { proxy: "http", request: "http", port: undefined, isProxyHttps: false }, { proxy: "hTtp", request: "https", port: 443, isProxyHttps: true }, { proxy: "HTTPS", request: "http", port: undefined, isProxyHttps: false }, - { proxy: "https", request: "hTTps", port: 443, isProxyHttps: true } - ].forEach(testCase => { - it(`should return ${testCase.isProxyHttps ? "HTTPS" : "HTTP"} proxy for ${testCase.proxy.toUpperCase()} proxy server and ${testCase.request.toUpperCase()} request`, function (done) { + { proxy: "https", request: "hTTps", port: 443, isProxyHttps: true }, + ].forEach((testCase) => { + it(`should return ${ + testCase.isProxyHttps ? "HTTPS" : "HTTP" + } proxy for ${testCase.proxy.toUpperCase()} proxy server and ${testCase.request.toUpperCase()} request`, function (done) { const urlHost = "proxy.microsoft.com"; const proxySettings = { host: `${testCase.proxy}://${urlHost}`, - port: 8080 + port: 8080, }; const requestUrl = `${testCase.request}://example.com`; @@ -48,10 +50,10 @@ describe("proxyAgent", () => { it("should copy headers correctly", function (done) { const proxySettings = { host: "http://proxy.microsoft.com", - port: 8080 + port: 8080, }; const headers = new HttpHeaders({ - "User-Agent": "Node.js" + "User-Agent": "Node.js", }); const proxyAgent = createProxyAgent("http://example.com", proxySettings, headers); @@ -65,24 +67,24 @@ describe("proxyAgent", () => { describe("createTunnel", () => { const defaultProxySettings = { host: "http://proxy.microsoft.com", - port: 8080 + port: 8080, }; type HttpsAgent = https.Agent & { - defaultPort: number | undefined, + defaultPort: number | undefined; options: { - proxy: tunnel.ProxyOptions - } + proxy: tunnel.ProxyOptions; + }; }; - [true, false].forEach(value => { + [true, false].forEach((value) => { it(`returns HTTP agent for HTTP request and HTTP${value ? "S" : ""} proxy`, function () { const tunnelConfig: tunnel.HttpsOverHttpsOptions = { proxy: { host: defaultProxySettings.host, port: defaultProxySettings.port, - headers: {} - } + headers: {}, + }, }; const tunnel = createTunnel(false, value, tunnelConfig) as HttpsAgent; @@ -92,14 +94,14 @@ describe("proxyAgent", () => { }); }); - [true, false].forEach(value => { + [true, false].forEach((value) => { it(`returns HTTPS agent for HTTPS request and HTTP${value ? "S" : ""} proxy`, function () { const tunnelConfig: tunnel.HttpsOverHttpsOptions = { proxy: { host: defaultProxySettings.host, port: defaultProxySettings.port, - headers: {} - } + headers: {}, + }, }; const tunnel = createTunnel(true, value, tunnelConfig) as HttpsAgent; diff --git a/test/serializationTests.ts b/test/serializationTests.ts index 3000757..aaded78 100644 --- a/test/serializationTests.ts +++ b/test/serializationTests.ts @@ -59,30 +59,30 @@ describe("msrest", function () { it("should correctly serialize a complex JSON object", function (done) { const o1: unknown = { - "p1": "value1", - "p2": "value2", + p1: "value1", + p2: "value2", "top-buf": stringToByteArray("top string"), "top-date": new Date("2014"), "top-dates": [new Date("1900"), new Date("1901")], - "insider": { + insider: { "insider-buf": stringToByteArray("insider string"), "insider-date": new Date("2015"), "insider-dates": [new Date("2100"), new Date("2101")], "insider-dictionary": { - "k1": new Date("2015"), - "k2": new Date("2016"), - "k3": new Date("2017") + k1: new Date("2015"), + k2: new Date("2016"), + k3: new Date("2017"), }, "top-complex": { - "id": 1, - "name": "Joey", - "age": 23.36, - "male": true, - "birthday": "1992-01-01T00:00:00.000Z", - "anniversary": new Date("2013-12-08"), - "memory": stringToByteArray("Yadadadada") - } - } + id: 1, + name: "Joey", + age: 23.36, + male: true, + birthday: "1992-01-01T00:00:00.000Z", + anniversary: new Date("2013-12-08"), + memory: stringToByteArray("Yadadadada"), + }, + }, }; const o2: unknown = { @@ -90,21 +90,15 @@ describe("msrest", function () { p2: "value2", "top-buf": "dG9wIHN0cmluZw==", "top-date": "2014-01-01T00:00:00.000Z", - "top-dates": [ - "1900-01-01T00:00:00.000Z", - "1901-01-01T00:00:00.000Z" - ], + "top-dates": ["1900-01-01T00:00:00.000Z", "1901-01-01T00:00:00.000Z"], insider: { "insider-buf": "aW5zaWRlciBzdHJpbmc=", "insider-date": "2015-01-01T00:00:00.000Z", - "insider-dates": [ - "2100-01-01T00:00:00.000Z", - "2101-01-01T00:00:00.000Z" - ], + "insider-dates": ["2100-01-01T00:00:00.000Z", "2101-01-01T00:00:00.000Z"], "insider-dictionary": { k1: "2015-01-01T00:00:00.000Z", k2: "2016-01-01T00:00:00.000Z", - k3: "2017-01-01T00:00:00.000Z" + k3: "2017-01-01T00:00:00.000Z", }, "top-complex": { id: 1, @@ -113,9 +107,9 @@ describe("msrest", function () { male: true, birthday: "1992-01-01T00:00:00.000Z", anniversary: "2013-12-08T00:00:00.000Z", - memory: "WWFkYWRhZGFkYQ==" - } - } + memory: "WWFkYWRhZGFkYQ==", + }, + }, }; assert.deepEqual(msRest.serializeObject(o1), o2); done(); @@ -125,76 +119,118 @@ describe("msrest", function () { describe("serialize", function () { const invalid_uuid = "abcd-efgd90-90890jkh"; it("should correctly serialize a string if the type is 'any'", function (done) { - const mapper: msRest.Mapper = { type: { name: "any" }, required: false, serializedName: "any" }; + const mapper: msRest.Mapper = { + type: { name: "any" }, + required: false, + serializedName: "any", + }; const serializedObject = Serializer.serialize(mapper, "foo", "anyBody"); serializedObject.should.equal("foo"); done(); }); it("should correctly serialize an array if the type is 'any'", function (done) { - const mapper: msRest.Mapper = { type: { name: "any" }, required: false, serializedName: "any" }; + const mapper: msRest.Mapper = { + type: { name: "any" }, + required: false, + serializedName: "any", + }; const serializedObject = Serializer.serialize(mapper, [1, 2], "anyBody"); assert.deepEqual(serializedObject, [1, 2]); done(); }); it("should correctly serialize a string", function (done) { - const mapper: msRest.Mapper = { type: { name: "String" }, required: false, serializedName: "string" }; + const mapper: msRest.Mapper = { + type: { name: "String" }, + required: false, + serializedName: "string", + }; const serializedObject = Serializer.serialize(mapper, "foo", "stringBody"); serializedObject.should.equal("foo"); done(); }); it("should correctly serialize a uuid", function (done) { - const mapper: msRest.Mapper = { type: { name: "Uuid" }, required: false, serializedName: "Uuid" }; + const mapper: msRest.Mapper = { + type: { name: "Uuid" }, + required: false, + serializedName: "Uuid", + }; const serializedObject = Serializer.serialize(mapper, valid_uuid, "uuidBody"); serializedObject.should.equal(valid_uuid); done(); }); it("should throw an error if the value is not a valid Uuid", function (done) { - const mapper: msRest.Mapper = { type: { name: "Uuid" }, required: false, serializedName: "Uuid" }; + const mapper: msRest.Mapper = { + type: { name: "Uuid" }, + required: false, + serializedName: "Uuid", + }; try { Serializer.serialize(mapper, invalid_uuid, "uuidBody"); } catch (error) { - error.message.should.match(/.*with value.*must be of type string and a valid uuid/ig); + error.message.should.match(/.*with value.*must be of type string and a valid uuid/gi); done(); } }); it("should correctly serialize a number", function (done) { - const mapper: msRest.Mapper = { type: { name: "Number" }, required: false, serializedName: "Number" }; + const mapper: msRest.Mapper = { + type: { name: "Number" }, + required: false, + serializedName: "Number", + }; const serializedObject = Serializer.serialize(mapper, 1.506, "stringBody"); serializedObject.should.equal(1.506); done(); }); it("should correctly serialize a boolean", function (done) { - const mapper: msRest.Mapper = { type: { name: "Boolean" }, required: false, serializedName: "Boolean" }; + const mapper: msRest.Mapper = { + type: { name: "Boolean" }, + required: false, + serializedName: "Boolean", + }; const serializedObject = Serializer.serialize(mapper, false, "stringBody"); serializedObject.should.equal(false); done(); }); it("should correctly serialize an Enum", function (done) { - const mapper: msRest.EnumMapper = { type: { name: "Enum", allowedValues: [1, 2, 3, 4] }, required: false, serializedName: "Enum" }; + const mapper: msRest.EnumMapper = { + type: { name: "Enum", allowedValues: [1, 2, 3, 4] }, + required: false, + serializedName: "Enum", + }; const serializedObject = Serializer.serialize(mapper, 1, "enumBody"); serializedObject.should.equal(1); done(); }); it("should throw an error if the value is not valid for an Enum", function (done) { - const mapper: msRest.EnumMapper = { type: { name: "Enum", allowedValues: [1, 2, 3, 4] }, required: false, serializedName: "Enum" }; + const mapper: msRest.EnumMapper = { + type: { name: "Enum", allowedValues: [1, 2, 3, 4] }, + required: false, + serializedName: "Enum", + }; try { Serializer.serialize(mapper, 6, "enumBody"); } catch (error) { - error.message.should.match(/6 is not a valid value for enumBody\. The valid values are: \[1,2,3,4\]/ig); + error.message.should.match( + /6 is not a valid value for enumBody\. The valid values are: \[1,2,3,4\]/gi + ); done(); } }); it("should correctly serialize a ByteArray Object", function (done) { - const mapper: msRest.Mapper = { type: { name: "ByteArray" }, required: false, serializedName: "ByteArray" }; + const mapper: msRest.Mapper = { + type: { name: "ByteArray" }, + required: false, + serializedName: "ByteArray", + }; const byteArray = stringToByteArray("Javascript"); const base64str = "SmF2YXNjcmlwdA=="; const serializedObject = Serializer.serialize(mapper, byteArray, "stringBody"); @@ -205,27 +241,51 @@ describe("msrest", function () { it("should correctly serialize a Date Object", function (done) { const dateObj = new Date("2015-01-01"); const dateISO = "2015-01-01"; - const mapper: msRest.Mapper = { type: { name: "Date" }, required: false, serializedName: "Date" }; + const mapper: msRest.Mapper = { + type: { name: "Date" }, + required: false, + serializedName: "Date", + }; Serializer.serialize(mapper, dateObj, "dateObj").should.equal(dateISO); done(); }); it("should correctly serialize a Date object with max value", function (done) { - const mapper: msRest.Mapper = { type: { name: "DateTime" }, required: false, serializedName: "DateTime" }; - const serializedDateString = Serializer.serialize(mapper, new Date("9999-12-31T23:59:59-12:00"), "dateTimeObj"); + const mapper: msRest.Mapper = { + type: { name: "DateTime" }, + required: false, + serializedName: "DateTime", + }; + const serializedDateString = Serializer.serialize( + mapper, + new Date("9999-12-31T23:59:59-12:00"), + "dateTimeObj" + ); serializedDateString.should.equal("+010000-01-01T11:59:59.000Z"); done(); }); it("should correctly serialize a Date object with max value and format UnixTime", function (done) { - const mapper: msRest.Mapper = { type: { name: "UnixTime" }, required: false, serializedName: "UnixTime" }; - const serializedDate = Serializer.serialize(mapper, new Date("9999-12-31T23:59:59-12:00"), "dateTimeObj"); + const mapper: msRest.Mapper = { + type: { name: "UnixTime" }, + required: false, + serializedName: "UnixTime", + }; + const serializedDate = Serializer.serialize( + mapper, + new Date("9999-12-31T23:59:59-12:00"), + "dateTimeObj" + ); serializedDate.should.equal(253402343999); done(); }); it("should correctly serialize a string in DateTimeRfc1123", function (done) { - const mapper: msRest.Mapper = { type: { name: "DateTimeRfc1123" }, required: false, serializedName: "DateTimeRfc1123" }; + const mapper: msRest.Mapper = { + type: { name: "DateTimeRfc1123" }, + required: false, + serializedName: "DateTimeRfc1123", + }; const rfc = new Date("Mon, 01 Jan 0001 00:00:00 GMT"); const serializedDateString = Serializer.serialize(mapper, rfc, "dateTimeObj"); serializedDateString.should.equal("Mon, 01 Jan 2001 00:00:00 GMT"); @@ -233,16 +293,26 @@ describe("msrest", function () { }); it("should correctly serialize an ISO 8601 duration", function () { - const mapper: msRest.Mapper = { type: { name: "TimeSpan" }, required: false, serializedName: "TimeSpan" }; + const mapper: msRest.Mapper = { + type: { name: "TimeSpan" }, + required: false, + serializedName: "TimeSpan", + }; const duration = "P123DT22H14M12.011S"; const serializedDateString = Serializer.serialize(mapper, duration, "dateTimeObj"); serializedDateString.should.equal(duration); }); it("should throw an error when given an invalid ISO 8601 duration", function () { - const mapper: msRest.Mapper = { type: { name: "TimeSpan" }, required: false, serializedName: "TimeSpan" }; + const mapper: msRest.Mapper = { + type: { name: "TimeSpan" }, + required: false, + serializedName: "TimeSpan", + }; const duration = "P123Z42DT22H14M12.011S"; - (() => Serializer.serialize(mapper, duration, "dateTimeObj")).should.throw(/must be a string in ISO 8601 format/); + (() => Serializer.serialize(mapper, duration, "dateTimeObj")).should.throw( + /must be a string in ISO 8601 format/ + ); }); it("should correctly serialize an array of primitives", function (done) { @@ -254,9 +324,9 @@ describe("msrest", function () { element: { type: { name: "String" }, required: true, - serializedName: "sequenceElement" - } - } + serializedName: "sequenceElement", + }, + }, }; const array = ["One", "Two", "three"]; const serializedArray = Serializer.serialize(mapper, array, "arrayObj"); @@ -279,12 +349,12 @@ describe("msrest", function () { required: true, serializedName: "sequenceElement", type: { - name: "Number" - } - } - } - } - } + name: "Number", + }, + }, + }, + }, + }, }; const array = [[1], [2], [1, 2, 3]]; const serializedArray = Serializer.serialize(mapper, array, "arrayObj"); @@ -303,12 +373,12 @@ describe("msrest", function () { name: "Sequence", element: { type: { - name: "Object" - } - } - } - } - } + name: "Object", + }, + }, + }, + }, + }, }; const array = [[1], ["2"], [1, "2", {}, true, []]]; const serializedArray = Serializer.serialize(mapper, array, mapper.serializedName); @@ -328,12 +398,12 @@ describe("msrest", function () { element: { required: true, type: { - name: "Object" - } - } - } - } - } + name: "Object", + }, + }, + }, + }, + }, }; const array = [[1], ["2"], [undefined], [1, "2", {}, true, []]]; try { @@ -344,7 +414,6 @@ describe("msrest", function () { done(); }); - it("should correctly serialize an array of dictionary of primitives", function (done) { const mapper: msRest.SequenceMapper = { required: false, @@ -360,12 +429,12 @@ describe("msrest", function () { required: true, serializedName: "valueElement", type: { - name: "Boolean" - } - } - } - } - } + name: "Boolean", + }, + }, + }, + }, + }, }; const array = [{ 1: true }, { 2: false }, { 1: true, 2: false, 3: true }]; const serializedArray = Serializer.serialize(mapper, array, "arrayObj"); @@ -383,10 +452,10 @@ describe("msrest", function () { required: true, serializedName: "valueElement", type: { - name: "String" - } - } - } + name: "String", + }, + }, + }, }; const dict = { 1: "One", 2: "Two", 3: "three" }; const serializedDictionary = Serializer.serialize(mapper, dict, "dictObj"); @@ -409,14 +478,14 @@ describe("msrest", function () { required: true, serializedName: "sequenceElement", type: { - name: "Number" - } - } - } - } - } + name: "Number", + }, + }, + }, + }, + }, }; - const dict = { "One": [1], "Two": [1, 2], "three": [1, 2, 3] }; + const dict = { One: [1], Two: [1, 2], three: [1, 2, 3] }; const serializedDictionary = Serializer.serialize(mapper, dict, "dictObj"); assert.deepEqual(dict, serializedDictionary); done(); @@ -437,14 +506,14 @@ describe("msrest", function () { required: true, serializedName: "valueElement", type: { - name: "Boolean" - } - } - } - } - } + name: "Boolean", + }, + }, + }, + }, + }, }; - const dict = { 1: { "One": true }, 2: { "Two": false }, 3: { "three": true } }; + const dict = { 1: { One: true }, 2: { Two: false }, 3: { three: true } }; const serializedDictionary = Serializer.serialize(mapper, dict, "dictObj"); assert.deepEqual(dict, serializedDictionary); done(); @@ -459,7 +528,7 @@ describe("msrest", function () { provisioningState: "Succeeded", tags: { tag1: "value1", - tag2: "value2" + tag2: "value2", }, dispatchTime: new Date("2015-01-01T12:35:36.009Z"), invoiceInfo: { @@ -467,18 +536,18 @@ describe("msrest", function () { invDate: "2015-12-25", invProducts: [ { - "Product1": { + Product1: { id: 101, - name: "TestProduct" - } + name: "TestProduct", + }, }, { - "Product2": { + Product2: { id: 104, - name: "TestProduct1" - } - } - ] + name: "TestProduct1", + }, + }, + ], }, subProducts: [ { @@ -487,8 +556,8 @@ describe("msrest", function () { makeTime: new Date("2015-12-21T01:01:01"), invoiceInfo: { invId: 1002, - invDate: "2015-12-25" - } + invDate: "2015-12-25", + }, }, { subId: 103, @@ -496,10 +565,10 @@ describe("msrest", function () { makeTime: new Date("2015-12-21T01:01:01"), invoiceInfo: { invId: 1003, - invDate: "2015-12-25" - } - } - ] + invDate: "2015-12-25", + }, + }, + ], }; const serializedProduct = client.serializer.serialize(mapper, productObj, "productObject"); for (const prop in serializedProduct) { @@ -512,11 +581,19 @@ describe("msrest", function () { } else if (prop === "tags") { JSON.stringify(serializedProduct[prop]).should.equal(JSON.stringify(productObj.tags)); } else if (prop === "dispatchTime") { - JSON.stringify(serializedProduct[prop]).should.equal(JSON.stringify(productObj.dispatchTime)); + JSON.stringify(serializedProduct[prop]).should.equal( + JSON.stringify(productObj.dispatchTime) + ); } else if (prop === "invoiceInfo") { - (JSON.stringify(serializedProduct[prop]).length - JSON.stringify(productObj.invoiceInfo).length).should.equal(4); + ( + JSON.stringify(serializedProduct[prop]).length - + JSON.stringify(productObj.invoiceInfo).length + ).should.equal(4); } else if (prop === "subProducts") { - (JSON.stringify(serializedProduct[prop]).length - JSON.stringify(productObj.subProducts).length).should.equal(8); + ( + JSON.stringify(serializedProduct[prop]).length - + JSON.stringify(productObj.subProducts).length + ).should.equal(8); } } done(); @@ -526,29 +603,29 @@ describe("msrest", function () { const client = new TestClient("http://localhost:9090"); const mapper = Mappers.SawShark; const sawshark = { - "fishtype": "sawshark", - "age": 22, - "birthday": new Date("2012-01-05T01:00:00Z"), - "species": "king", - "length": 1.0, - "picture": new Uint8Array([255, 255, 255, 255, 254]), - "siblings": [ + fishtype: "sawshark", + age: 22, + birthday: new Date("2012-01-05T01:00:00Z"), + species: "king", + length: 1.0, + picture: new Uint8Array([255, 255, 255, 255, 254]), + siblings: [ { - "fishtype": "shark", - "age": 6, - "birthday": new Date("2012-01-05T01:00:00Z"), - "length": 20.0, - "species": "predator" + fishtype: "shark", + age: 6, + birthday: new Date("2012-01-05T01:00:00Z"), + length: 20.0, + species: "predator", }, { - "fishtype": "sawshark", - "age": 105, - "birthday": new Date("1900-01-05T01:00:00Z"), - "length": 10.0, - "picture": new Uint8Array([255, 255, 255, 255, 254]), - "species": "dangerous" - } - ] + fishtype: "sawshark", + age: 105, + birthday: new Date("1900-01-05T01:00:00Z"), + length: 10.0, + picture: new Uint8Array([255, 255, 255, 255, 254]), + species: "dangerous", + }, + ], }; const serializedSawshark = client.serializer.serialize(mapper, sawshark, "result"); serializedSawshark.age.should.equal(22); @@ -556,10 +633,14 @@ describe("msrest", function () { serializedSawshark.siblings.length.should.equal(2); serializedSawshark.siblings[0]["fish.type"].should.equal("shark"); serializedSawshark.siblings[0].age.should.equal(6); - serializedSawshark.siblings[0].birthday.should.equal(new Date("2012-01-05T01:00:00Z").toISOString()); + serializedSawshark.siblings[0].birthday.should.equal( + new Date("2012-01-05T01:00:00Z").toISOString() + ); serializedSawshark.siblings[1]["fish.type"].should.equal("sawshark"); serializedSawshark.siblings[1].age.should.equal(105); - serializedSawshark.siblings[1].birthday.should.equal(new Date("1900-01-05T01:00:00Z").toISOString()); + serializedSawshark.siblings[1].birthday.should.equal( + new Date("1900-01-05T01:00:00Z").toISOString() + ); serializedSawshark.siblings[1].picture.should.equal("//////4="); serializedSawshark.picture.should.equal("//////4="); done(); @@ -573,12 +654,12 @@ describe("msrest", function () { additionalProperties1: { height: 5.61, weight: 599, - footsize: 11.5 + footsize: 11.5, }, color: "red", city: "Seattle", food: "tikka masala", - birthdate: "2017-12-13T02:29:51.000Z" + birthdate: "2017-12-13T02:29:51.000Z", }; const client = new TestClient("http://localhost:9090"); const mapper = Mappers.PetAP; @@ -610,11 +691,11 @@ describe("msrest", function () { nullable: true, serializedName: "length", type: { - name: "Number" - } - } - } - } + name: "Number", + }, + }, + }, + }, }; // tslint:disable-next-line @@ -635,14 +716,16 @@ describe("msrest", function () { nullable: true, serializedName: "length", type: { - name: "Number" - } - } - } - } + name: "Number", + }, + }, + }, + }, }; - (function () { Serializer.serialize(mapper, { length: undefined }, "testobj"); }).should.throw("testobj.length cannot be undefined."); + (function () { + Serializer.serialize(mapper, { length: undefined }, "testobj"); + }.should.throw("testobj.length cannot be undefined.")); }); it("should not allow null when required: true and nullable: false", function () { @@ -658,14 +741,16 @@ describe("msrest", function () { nullable: false, serializedName: "length", type: { - name: "Number" - } - } - } - } + name: "Number", + }, + }, + }, + }, }; - (function () { Serializer.serialize(mapper, { length: undefined }, "testobj"); }).should.throw("testobj.length cannot be null or undefined."); + (function () { + Serializer.serialize(mapper, { length: undefined }, "testobj"); + }.should.throw("testobj.length cannot be null or undefined.")); }); it("should not allow undefined when required: true and nullable: false", function () { @@ -681,14 +766,16 @@ describe("msrest", function () { nullable: false, serializedName: "length", type: { - name: "Number" - } - } - } - } + name: "Number", + }, + }, + }, + }, }; - (function () { Serializer.serialize(mapper, { length: undefined }, "testobj"); }).should.throw("testobj.length cannot be null or undefined."); + (function () { + Serializer.serialize(mapper, { length: undefined }, "testobj"); + }.should.throw("testobj.length cannot be null or undefined.")); }); it("should not allow null when required: true and nullable is undefined", function () { @@ -696,10 +783,12 @@ describe("msrest", function () { serializedName: "foo", required: true, type: { - name: "String" - } + name: "String", + }, }; - (function () { Serializer.serialize(mapper, undefined, "testobj"); }).should.throw("testobj cannot be null or undefined."); + (function () { + Serializer.serialize(mapper, undefined, "testobj"); + }.should.throw("testobj cannot be null or undefined.")); }); it("should not allow undefined when required: true and nullable is undefined", function () { @@ -707,10 +796,12 @@ describe("msrest", function () { serializedName: "foo", required: true, type: { - name: "String" - } + name: "String", + }, }; - (function () { Serializer.serialize(mapper, undefined, "testobj"); }).should.throw("testobj cannot be null or undefined."); + (function () { + Serializer.serialize(mapper, undefined, "testobj"); + }.should.throw("testobj cannot be null or undefined.")); }); it("should allow null when required: false and nullable: true", function () { @@ -719,8 +810,8 @@ describe("msrest", function () { required: false, nullable: true, type: { - name: "String" - } + name: "String", + }, }; Serializer.serialize(mapper, undefined, "testobj"); @@ -732,12 +823,14 @@ describe("msrest", function () { required: false, nullable: false, type: { - name: "String" - } + name: "String", + }, }; - // tslint:disable-next-line - (function () { Serializer.serialize(mapper, null, "testobj"); }).should.throw("testobj cannot be null."); + (function () { + /* tslint:disable-next-line:no-null-keyword */ + Serializer.serialize(mapper, null, "testobj"); + }.should.throw("testobj cannot be null.")); }); it("should allow null when required: false and nullable is undefined", function () { @@ -745,8 +838,8 @@ describe("msrest", function () { serializedName: "foo", required: false, type: { - name: "String" - } + name: "String", + }, }; Serializer.serialize(mapper, undefined, "testobj"); @@ -758,8 +851,8 @@ describe("msrest", function () { required: false, nullable: true, type: { - name: "String" - } + name: "String", + }, }; Serializer.serialize(mapper, undefined, "testobj"); @@ -777,11 +870,11 @@ describe("msrest", function () { required: false, nullable: false, type: { - name: "String" - } - } - } - } + name: "String", + }, + }, + }, + }, }; Serializer.serialize(mapper, { length: undefined }, "testobj"); @@ -792,8 +885,8 @@ describe("msrest", function () { serializedName: "foo", required: false, type: { - name: "String" - } + name: "String", + }, }; Serializer.serialize(mapper, undefined, "testobj"); @@ -802,21 +895,33 @@ describe("msrest", function () { describe("deserialize", function () { it("should correctly deserialize a Date if the type is 'any'", function (done) { - const mapper: msRest.Mapper = { type: { name: "any" }, required: false, serializedName: "any" }; + const mapper: msRest.Mapper = { + type: { name: "any" }, + required: false, + serializedName: "any", + }; const d = new Date(); const deserializedObject = Serializer.deserialize(mapper, d, "anyResponseBody"); deserializedObject.should.equal(d); done(); }); it("should correctly deserialize an array if the type is 'any'", function (done) { - const mapper: msRest.Mapper = { type: { name: "any" }, required: false, serializedName: "any" }; + const mapper: msRest.Mapper = { + type: { name: "any" }, + required: false, + serializedName: "any", + }; const buf = [1, 2, 3]; const deserializedObject = Serializer.deserialize(mapper, buf, "anyBody"); deserializedObject.should.equal(buf); done(); }); it("should correctly deserialize a uuid", function (done) { - const mapper: msRest.Mapper = { type: { name: "Uuid" }, required: false, serializedName: "Uuid" }; + const mapper: msRest.Mapper = { + type: { name: "Uuid" }, + required: false, + serializedName: "Uuid", + }; const serializedObject = Serializer.deserialize(mapper, valid_uuid, "uuidBody"); serializedObject.should.equal(valid_uuid); done(); @@ -828,11 +933,11 @@ describe("msrest", function () { id: 101, name: "TestProduct", properties: { - provisioningState: "Succeeded" + provisioningState: "Succeeded", }, tags: { tag1: "value1", - tag2: "value2" + tag2: "value2", }, dispatchTime: new Date("2015-01-01T12:35:36.009Z"), invoiceInfo: { @@ -840,18 +945,18 @@ describe("msrest", function () { invDate: "2015-12-25", invProducts: [ { - "Product1": { + Product1: { id: 101, - name: "TestProduct" - } + name: "TestProduct", + }, }, { - "Product2": { + Product2: { id: 104, - name: "TestProduct1" - } - } - ] + name: "TestProduct1", + }, + }, + ], }, subProducts: [ { @@ -860,8 +965,8 @@ describe("msrest", function () { makeTime: new Date("2015-12-21T01:01:01"), invoiceInfo: { invoiceId: 1002, - invDate: "2015-12-25" - } + invDate: "2015-12-25", + }, }, { subId: 103, @@ -869,15 +974,21 @@ describe("msrest", function () { makeTime: new Date("2015-12-21T01:01:01"), invoiceInfo: { invoiceId: 1003, - invDate: "2015-12-25" - } - } - ] + invDate: "2015-12-25", + }, + }, + ], }; - const deserializedProduct = client.serializer.deserialize(mapper, responseBody, "responseBody"); + const deserializedProduct = client.serializer.deserialize( + mapper, + responseBody, + "responseBody" + ); for (const prop in deserializedProduct) { if (prop === "provisioningState") { - deserializedProduct.provisioningState.should.equal(responseBody.properties.provisioningState); + deserializedProduct.provisioningState.should.equal( + responseBody.properties.provisioningState + ); } else if (prop === "id") { deserializedProduct[prop].should.equal(responseBody.id); } else if (prop === "name") { @@ -885,11 +996,19 @@ describe("msrest", function () { } else if (prop === "tags") { JSON.stringify(deserializedProduct[prop]).should.equal(JSON.stringify(responseBody.tags)); } else if (prop === "dispatchTime") { - JSON.stringify(deserializedProduct[prop]).should.equal(JSON.stringify(responseBody.dispatchTime)); + JSON.stringify(deserializedProduct[prop]).should.equal( + JSON.stringify(responseBody.dispatchTime) + ); } else if (prop === "invoiceInfo") { - (JSON.stringify(deserializedProduct[prop]).length - JSON.stringify(responseBody.invoiceInfo).length).should.equal(10); + ( + JSON.stringify(deserializedProduct[prop]).length - + JSON.stringify(responseBody.invoiceInfo).length + ).should.equal(10); } else if (prop === "subProducts") { - (JSON.stringify(deserializedProduct[prop]).length - JSON.stringify(responseBody.subProducts).length).should.equal(20); + ( + JSON.stringify(deserializedProduct[prop]).length - + JSON.stringify(responseBody.subProducts).length + ).should.equal(20); } } done(); @@ -904,20 +1023,24 @@ describe("msrest", function () { id: 101, name: "TestProduct", properties: { - provisioningState: "Succeeded" - } + provisioningState: "Succeeded", + }, }, { id: 104, name: "TestProduct1", properties: { - provisioningState: "Failed" - } - } - ] + provisioningState: "Failed", + }, + }, + ], }; - const deserializedProduct = client.serializer.deserialize(mapper, responseBody, "responseBody"); - (Array.isArray(deserializedProduct)).should.be.true; + const deserializedProduct = client.serializer.deserialize( + mapper, + responseBody, + "responseBody" + ); + Array.isArray(deserializedProduct).should.be.true; deserializedProduct.length.should.equal(2); for (let i = 0; i < deserializedProduct.length; i++) { if (i === 0) { @@ -942,21 +1065,25 @@ describe("msrest", function () { id: 101, name: "TestProduct", properties: { - provisioningState: "Succeeded" - } + provisioningState: "Succeeded", + }, }, { id: 104, name: "TestProduct1", properties: { - provisioningState: "Failed" - } - } + provisioningState: "Failed", + }, + }, ], - nextLink: "https://helloworld.com" + nextLink: "https://helloworld.com", }; - const deserializedProduct = client.serializer.deserialize(mapper, responseBody, "responseBody"); - (Array.isArray(deserializedProduct)).should.be.true; + const deserializedProduct = client.serializer.deserialize( + mapper, + responseBody, + "responseBody" + ); + Array.isArray(deserializedProduct).should.be.true; deserializedProduct.length.should.equal(2); deserializedProduct.nextLink.should.equal("https://helloworld.com"); for (let i = 0; i < deserializedProduct.length; i++) { @@ -978,30 +1105,34 @@ describe("msrest", function () { const mapper = Mappers.Fish; const responseBody = { "fish.type": "sawshark", - "age": 22, - "birthday": new Date("2012-01-05T01:00:00Z").toISOString(), - "species": "king", - "length": 1.0, - "picture": "/////g==", - "siblings": [ + age: 22, + birthday: new Date("2012-01-05T01:00:00Z").toISOString(), + species: "king", + length: 1.0, + picture: "/////g==", + siblings: [ { "fish.type": "shark", - "age": 6, - "birthday": new Date("2012-01-05T01:00:00Z"), - "length": 20.0, - "species": "predator" + age: 6, + birthday: new Date("2012-01-05T01:00:00Z"), + length: 20.0, + species: "predator", }, { "fish.type": "sawshark", - "age": 105, - "birthday": new Date("1900-01-05T01:00:00Z").toISOString(), - "length": 10.0, - "picture": "/////g==", - "species": "dangerous" - } - ] + age: 105, + birthday: new Date("1900-01-05T01:00:00Z").toISOString(), + length: 10.0, + picture: "/////g==", + species: "dangerous", + }, + ], }; - const deserializedSawshark = client.serializer.deserialize(mapper, responseBody, "responseBody"); + const deserializedSawshark = client.serializer.deserialize( + mapper, + responseBody, + "responseBody" + ); deserializedSawshark.age.should.equal(22); deserializedSawshark.fishtype.should.equal("sawshark"); @@ -1015,10 +1146,14 @@ describe("msrest", function () { deserializedSawshark.siblings.length.should.equal(2); deserializedSawshark.siblings[0].fishtype.should.equal("shark"); deserializedSawshark.siblings[0].age.should.equal(6); - deserializedSawshark.siblings[0].birthday.toISOString().should.equal("2012-01-05T01:00:00.000Z"); + deserializedSawshark.siblings[0].birthday + .toISOString() + .should.equal("2012-01-05T01:00:00.000Z"); deserializedSawshark.siblings[1].fishtype.should.equal("sawshark"); deserializedSawshark.siblings[1].age.should.equal(105); - deserializedSawshark.siblings[1].birthday.toISOString().should.equal("1900-01-05T01:00:00.000Z"); + deserializedSawshark.siblings[1].birthday + .toISOString() + .should.equal("1900-01-05T01:00:00.000Z"); done(); }); @@ -1035,12 +1170,12 @@ describe("msrest", function () { element: { serializedName: "ObjectElementType", type: { - name: "Object" - } - } - } - } - } + name: "Object", + }, + }, + }, + }, + }, }; const array = [[1], ["2"], [1, "2", {}, true, []]]; const deserializedArray = Serializer.deserialize(mapper, array, mapper.serializedName!); @@ -1053,31 +1188,35 @@ describe("msrest", function () { const mapper = Mappers.Fish; const responseBody = { "fish.type": "sawshark", - "age": 22, - "birthday": new Date("2012-01-05T01:00:00Z").toISOString(), - "species": "king", - "length": 1.0, - "picture": "/////g==", - "siblings": [ + age: 22, + birthday: new Date("2012-01-05T01:00:00Z").toISOString(), + species: "king", + length: 1.0, + picture: "/////g==", + siblings: [ { "fish.type": "mutatedshark", - "age": 105, - "birthday": new Date("1900-01-05T01:00:00Z").toISOString(), - "length": 10.0, - "picture": "/////g==", - "species": "dangerous", - "siblings": [ + age: 105, + birthday: new Date("1900-01-05T01:00:00Z").toISOString(), + length: 10.0, + picture: "/////g==", + species: "dangerous", + siblings: [ { "fish.type": "mutatedshark", - "age": 6, - "length": 20.0, - "species": "predator" - } - ] - } - ] + age: 6, + length: 20.0, + species: "predator", + }, + ], + }, + ], }; - const deserializedSawshark = client.serializer.deserialize(mapper, responseBody, "responseBody"); + const deserializedSawshark = client.serializer.deserialize( + mapper, + responseBody, + "responseBody" + ); deserializedSawshark.siblings.length.should.equal(1); deserializedSawshark.siblings[0].fishtype.should.equal("mutatedshark"); deserializedSawshark.siblings[0].species.should.equal("dangerous"); @@ -1099,12 +1238,12 @@ describe("msrest", function () { additionalProperties: { height: 5.61, weight: 599, - footsize: 11.5 + footsize: 11.5, }, color: "red", city: "Seattle", food: "tikka masala", - birthdate: "2017-12-13T02:29:51Z" + birthdate: "2017-12-13T02:29:51Z", }; const client = new TestClient("http://localhost:9090"); const mapper = Mappers.PetAP; @@ -1129,31 +1268,35 @@ describe("msrest", function () { const client = new TestClient("http://localhost:9090"); const mapper = Mappers.Fish; const responseBody = { - "age": 22, - "birthday": new Date("2012-01-05T01:00:00Z").toISOString(), - "species": "king", - "length": 1.0, - "picture": Buffer.from([255, 255, 255, 255, 254]).toString(), - "siblings": [ + age: 22, + birthday: new Date("2012-01-05T01:00:00Z").toISOString(), + species: "king", + length: 1.0, + picture: Buffer.from([255, 255, 255, 255, 254]).toString(), + siblings: [ { "fish.type": "mutatedshark", - "age": 105, - "birthday": new Date("1900-01-05T01:00:00Z").toISOString(), - "length": 10.0, - "picture": Buffer.from([255, 255, 255, 255, 254]).toString(), - "species": "dangerous", - "siblings": [ + age: 105, + birthday: new Date("1900-01-05T01:00:00Z").toISOString(), + length: 10.0, + picture: Buffer.from([255, 255, 255, 255, 254]).toString(), + species: "dangerous", + siblings: [ { "fish.type": "mutatedshark", - "age": 6, - "length": 20.0, - "species": "predator" - } - ] - } - ] + age: 6, + length: 20.0, + species: "predator", + }, + ], + }, + ], }; - const deserializedSawshark = client.serializer.deserialize(mapper, responseBody, "responseBody"); + const deserializedSawshark = client.serializer.deserialize( + mapper, + responseBody, + "responseBody" + ); deserializedSawshark.fishtype.should.equal("Fish"); deserializedSawshark.siblings.length.should.equal(1); deserializedSawshark.siblings[0].fishtype.should.equal("mutatedshark"); @@ -1170,28 +1313,28 @@ describe("msrest", function () { const client = new TestClient("http://localhost:9090"); const mapper = Mappers.SawShark; const sawshark = { - "age": 22, - "birthday": new Date("2012-01-05T01:00:00Z"), - "species": "king", - "length": 1.0, - "picture": Buffer.from([255, 255, 255, 255, 254]), - "siblings": [ + age: 22, + birthday: new Date("2012-01-05T01:00:00Z"), + species: "king", + length: 1.0, + picture: Buffer.from([255, 255, 255, 255, 254]), + siblings: [ { - "fishtype": "shark", - "age": 6, - "birthday": new Date("2012-01-05T01:00:00Z"), - "length": 20.0, - "species": "predator" + fishtype: "shark", + age: 6, + birthday: new Date("2012-01-05T01:00:00Z"), + length: 20.0, + species: "predator", }, { - "fishtype": "sawshark", - "age": 105, - "birthday": new Date("1900-01-05T01:00:00Z"), - "length": 10.0, - "picture": Buffer.from([255, 255, 255, 255, 254]), - "species": "dangerous" - } - ] + fishtype: "sawshark", + age: 105, + birthday: new Date("1900-01-05T01:00:00Z"), + length: 10.0, + picture: Buffer.from([255, 255, 255, 255, 254]), + species: "dangerous", + }, + ], }; const serializedSawshark = client.serializer.serialize(mapper, sawshark, "result"); serializedSawshark.age.should.equal(22); @@ -1199,10 +1342,14 @@ describe("msrest", function () { serializedSawshark.siblings.length.should.equal(2); serializedSawshark.siblings[0]["fish.type"].should.equal("shark"); serializedSawshark.siblings[0].age.should.equal(6); - serializedSawshark.siblings[0].birthday.should.equal(new Date("2012-01-05T01:00:00Z").toISOString()); + serializedSawshark.siblings[0].birthday.should.equal( + new Date("2012-01-05T01:00:00Z").toISOString() + ); serializedSawshark.siblings[1]["fish.type"].should.equal("sawshark"); serializedSawshark.siblings[1].age.should.equal(105); - serializedSawshark.siblings[1].birthday.should.equal(new Date("1900-01-05T01:00:00Z").toISOString()); + serializedSawshark.siblings[1].birthday.should.equal( + new Date("1900-01-05T01:00:00Z").toISOString() + ); serializedSawshark.siblings[1].picture.should.equal("//////4="); serializedSawshark.picture.should.equal("//////4="); done(); @@ -1222,34 +1369,34 @@ describe("msrest", function () { value: { serializedName: "element", type: { - name: "String" - } - } + name: "String", + }, + }, }, - headerCollectionPrefix: "foo-bar-" + headerCollectionPrefix: "foo-bar-", }, unrelated: { serializedName: "unrelated", type: { - name: "Number" - } - } - } - } + name: "Number", + }, + }, + }, + }, }; const rawHeaders = { "foo-bar-alpha": "hello", "foo-bar-beta": "world", - "unrelated": "42" + unrelated: "42", }; const expected = { metadata: { - "alpha": "hello", - "beta": "world" + alpha: "hello", + beta: "world", }, - unrelated: 42 + unrelated: 42, }; const actual = Serializer.deserialize(mapper, rawHeaders, "headers"); assert.deepEqual(actual, expected); @@ -1263,7 +1410,7 @@ describe("msrest", function () { name: "Composite", polymorphicDiscriminator: { serializedName: "fishtype", - clientName: "fishtype" + clientName: "fishtype", }, uberParent: "Fish", className: "Fish", @@ -1272,11 +1419,11 @@ describe("msrest", function () { required: true, serializedName: "fishtype", type: { - name: "String" - } - } - } - } + name: "String", + }, + }, + }, + }, }; const shark: msRest.CompositeMapper = { @@ -1291,26 +1438,30 @@ describe("msrest", function () { age: { serializedName: "age", type: { - name: "Number" - } - } - } - } + name: "Number", + }, + }, + }, + }, }; const mappers = { Fish: fish, Shark: shark, discriminators: { - "Fish": fish, - "Fish.shark": shark - } + Fish: fish, + "Fish.shark": shark, + }, }; const serializer = new msRest.Serializer(mappers); - const result = serializer.deserialize(fish, { - fishtype: "shark", - age: 10 - }, ""); + const result = serializer.deserialize( + fish, + { + fishtype: "shark", + age: 10, + }, + "" + ); assert.strictEqual("shark", result.fishtype); assert.strictEqual(10, result.age); @@ -1323,7 +1474,7 @@ describe("msrest", function () { name: "Composite", polymorphicDiscriminator: { serializedName: "fishtype", - clientName: "fishtype" + clientName: "fishtype", }, uberParent: "Fish", className: "Fish", @@ -1335,21 +1486,21 @@ describe("msrest", function () { name: "Composite", polymorphicDiscriminator: { serializedName: "fishtype", - clientName: "fishtype" + clientName: "fishtype", }, uberParent: "Fish", - className: "Fish" - } + className: "Fish", + }, }, fishtype: { required: true, serializedName: "fishtype", type: { - name: "String" - } - } - } - } + name: "String", + }, + }, + }, + }, }; const shark: msRest.CompositeMapper = { @@ -1364,27 +1515,31 @@ describe("msrest", function () { age: { serializedName: "age", type: { - name: "Number" - } - } - } - } + name: "Number", + }, + }, + }, + }, }; const mappers = { Fish: fish, Shark: shark, discriminators: { - "Fish": fish, - "Fish.shark": shark - } + Fish: fish, + "Fish.shark": shark, + }, }; const serializer = new msRest.Serializer(mappers); - const result = serializer.deserialize(fish, { - fishtype: "shark", - age: 10, - sibling: { fishtype: "shark", age: 15 } - }, ""); + const result = serializer.deserialize( + fish, + { + fishtype: "shark", + age: 10, + sibling: { fishtype: "shark", age: 15 }, + }, + "" + ); assert.strictEqual("shark", result.fishtype); assert.strictEqual(10, result.age); @@ -1399,7 +1554,7 @@ describe("msrest", function () { name: "Composite", polymorphicDiscriminator: { serializedName: "fishtype", - clientName: "fishtype" + clientName: "fishtype", }, uberParent: "Fish", className: "Fish", @@ -1410,18 +1565,18 @@ describe("msrest", function () { type: { name: "Composite", uberParent: "Fish", - className: "Fish" - } + className: "Fish", + }, }, fishtype: { required: true, serializedName: "fishtype", type: { - name: "String" - } - } - } - } + name: "String", + }, + }, + }, + }, }; const shark: msRest.CompositeMapper = { @@ -1436,27 +1591,31 @@ describe("msrest", function () { age: { serializedName: "age", type: { - name: "Number" - } - } - } - } + name: "Number", + }, + }, + }, + }, }; const mappers = { Fish: fish, Shark: shark, discriminators: { - "Fish": fish, - "Fish.shark": shark - } + Fish: fish, + "Fish.shark": shark, + }, }; const serializer = new msRest.Serializer(mappers); - const result = serializer.deserialize(fish, { - fishtype: "shark", - age: 10, - sibling: { fishtype: "shark", age: 15 } - }, ""); + const result = serializer.deserialize( + fish, + { + fishtype: "shark", + age: 10, + sibling: { fishtype: "shark", age: 15 }, + }, + "" + ); assert.strictEqual("shark", result.fishtype); assert.strictEqual(10, result.age); @@ -1470,12 +1629,12 @@ describe("msrest", function () { type: { name: "Composite", className: "Fish", - modelProperties: {} - } + modelProperties: {}, + }, }; const mappers = { - Fish: fish + Fish: fish, }; const serializer = new msRest.Serializer(mappers); const result: any = serializer.deserialize(fish, "", "mockFishProperty"); @@ -1491,7 +1650,7 @@ describe("msrest", function () { name: "Composite", polymorphicDiscriminator: { serializedName: "fishtype", - clientName: "fishtype" + clientName: "fishtype", }, uberParent: "Fish", className: "Fish", @@ -1499,15 +1658,15 @@ describe("msrest", function () { species: { serializedName: "species", type: { - name: "String" - } + name: "String", + }, }, length: { required: true, serializedName: "length", type: { - name: "Number" - } + name: "Number", + }, }, siblings: { serializedName: "siblings", @@ -1516,20 +1675,20 @@ describe("msrest", function () { element: { type: { name: "Composite", - className: "Fish" - } - } - } + className: "Fish", + }, + }, + }, }, fishtype: { required: true, serializedName: "fishtype", type: { - name: "String" - } - } - } - } + name: "String", + }, + }, + }, + }, }; const Salmon: msRest.CompositeMapper = { @@ -1544,17 +1703,17 @@ describe("msrest", function () { location: { serializedName: "location", type: { - name: "String" - } + name: "String", + }, }, iswild: { serializedName: "iswild", type: { - name: "Boolean" - } - } - } - } + name: "Boolean", + }, + }, + }, + }, }; const Shark: msRest.CompositeMapper = { @@ -1569,18 +1728,18 @@ describe("msrest", function () { age: { serializedName: "age", type: { - name: "Number" - } + name: "Number", + }, }, birthday: { required: true, serializedName: "birthday", type: { - name: "DateTime" - } - } - } - } + name: "DateTime", + }, + }, + }, + }, }; const Sawshark: msRest.CompositeMapper = { @@ -1595,11 +1754,11 @@ describe("msrest", function () { picture: { serializedName: "picture", type: { - name: "ByteArray" - } - } - } - } + name: "ByteArray", + }, + }, + }, + }, }; const Goblinshark: msRest.CompositeMapper = { @@ -1614,23 +1773,23 @@ describe("msrest", function () { jawsize: { serializedName: "jawsize", type: { - name: "Number" - } + name: "Number", + }, }, color: { serializedName: "color", defaultValue: "gray", type: { - name: "String" - } - } - } - } + name: "String", + }, + }, + }, + }, }; const mappers = { discriminators: { - "Fish": Fish, + Fish: Fish, "Fish.salmon": Salmon, "Fish.shark": Shark, "Fish.sawshark": Sawshark, @@ -1645,32 +1804,37 @@ describe("msrest", function () { it("should be deserialized with child properties", function () { const body = { - "fishtype": "salmon", - "location": "alaska", - "iswild": true, - "species": "king", - "length": 1, - "siblings": [{ - "fishtype": "shark", - "age": 6, - "birthday": "2012-01-05T01:00:00Z", - "length": 20, - "species": "predator" - }, { - "fishtype": "sawshark", - "age": 105, - "birthday": "1900-01-05T01:00:00Z", - "length": 10, - "picture": "//////4=", - "species": "dangerous" - }, { - "fishtype": "goblin", - "age": 1, "birthday": "2015-08-08T00:00:00Z", - "length": 30, - "species": "scary", - "jawsize": 5, - "color": "pinkish-gray" - }] + fishtype: "salmon", + location: "alaska", + iswild: true, + species: "king", + length: 1, + siblings: [ + { + fishtype: "shark", + age: 6, + birthday: "2012-01-05T01:00:00Z", + length: 20, + species: "predator", + }, + { + fishtype: "sawshark", + age: 105, + birthday: "1900-01-05T01:00:00Z", + length: 10, + picture: "//////4=", + species: "dangerous", + }, + { + fishtype: "goblin", + age: 1, + birthday: "2015-08-08T00:00:00Z", + length: 30, + species: "scary", + jawsize: 5, + color: "pinkish-gray", + }, + ], }; const serializer = new msRest.Serializer(mappers); @@ -1683,37 +1847,37 @@ describe("msrest", function () { it("should be serialized with child properties", function () { const body = { - "fishtype": "salmon", - "location": "alaska", - "iswild": true, - "species": "king", - "length": 1.0, - "siblings": [ + fishtype: "salmon", + location: "alaska", + iswild: true, + species: "king", + length: 1.0, + siblings: [ { - "fishtype": "shark", - "age": 6, - "birthday": new Date("2012-01-05T01:00:00Z"), - "length": 20.0, - "species": "predator" + fishtype: "shark", + age: 6, + birthday: new Date("2012-01-05T01:00:00Z"), + length: 20.0, + species: "predator", }, { - "fishtype": "sawshark", - "age": 105, - "birthday": new Date("1900-01-05T01:00:00Z"), - "length": 10.0, - "picture": new Uint8Array([255, 255, 255, 255, 254]), - "species": "dangerous" + fishtype: "sawshark", + age: 105, + birthday: new Date("1900-01-05T01:00:00Z"), + length: 10.0, + picture: new Uint8Array([255, 255, 255, 255, 254]), + species: "dangerous", }, { - "fishtype": "goblin", - "color": "pinkish-gray", - "age": 1, - "length": 30, - "species": "scary", - "birthday": new Date("2015-08-08T00:00:00Z"), - "jawsize": 5 - } - ] + fishtype: "goblin", + color: "pinkish-gray", + age: 1, + length: 30, + species: "scary", + birthday: new Date("2015-08-08T00:00:00Z"), + jawsize: 5, + }, + ], }; const serializer = new msRest.Serializer(mappers); diff --git a/test/serviceClientTests.ts b/test/serviceClientTests.ts index 2746131..1cc5ae2 100644 --- a/test/serviceClientTests.ts +++ b/test/serviceClientTests.ts @@ -5,9 +5,19 @@ import { assert } from "chai"; import { HttpClient } from "../lib/httpClient"; import { QueryCollectionFormat } from "../lib/queryCollectionFormat"; import { DictionaryMapper, MapperType, Serializer, Mapper } from "../lib/serializer"; -import { serializeRequestBody, ServiceClient, getOperationArgumentValueFromParameterPath } from "../lib/serviceClient"; +import { + serializeRequestBody, + ServiceClient, + getOperationArgumentValueFromParameterPath, +} from "../lib/serviceClient"; import { WebResourceLike, WebResource } from "../lib/webResource"; -import { OperationArguments, HttpHeaders, deserializationPolicy, RestResponse, isNode } from "../lib/msRest"; +import { + OperationArguments, + HttpHeaders, + deserializationPolicy, + RestResponse, + isNode, +} from "../lib/msRest"; import { ParameterPath } from "../lib/operationParameter"; describe("ServiceClient", function () { @@ -15,59 +25,63 @@ describe("ServiceClient", function () { const expected = { "foo-bar-alpha": "hello", "foo-bar-beta": "world", - "unrelated": "42" + unrelated: "42", }; let request: WebResourceLike; const client = new ServiceClient(undefined, { httpClient: { - sendRequest: req => { + sendRequest: (req) => { request = req; return Promise.resolve({ request, status: 200, headers: new HttpHeaders() }); - } + }, }, - requestPolicyFactories: [] + requestPolicyFactories: [], }); await client.sendOperationRequest( { metadata: { - "alpha": "hello", - "beta": "world" + alpha: "hello", + beta: "world", }, - unrelated: 42 + unrelated: 42, }, { httpMethod: "GET", baseUrl: "httpbin.org", serializer: new Serializer(), - headerParameters: [{ - parameterPath: "metadata", - mapper: { - serializedName: "metadata", - type: { - name: "Dictionary", - value: { - type: { - name: "String" - } - } + headerParameters: [ + { + parameterPath: "metadata", + mapper: { + serializedName: "metadata", + type: { + name: "Dictionary", + value: { + type: { + name: "String", + }, + }, + }, + headerCollectionPrefix: "foo-bar-", + } as DictionaryMapper, + }, + { + parameterPath: "unrelated", + mapper: { + serializedName: "unrelated", + type: { + name: "Number", + }, }, - headerCollectionPrefix: "foo-bar-" - } as DictionaryMapper - }, { - parameterPath: "unrelated", - mapper: { - serializedName: "unrelated", - type: { - name: "Number" - } - } - }], + }, + ], responses: { - 200: {} - } - }); + 200: {}, + }, + } + ); assert(request!); assert.deepEqual(request!.headers.toJson(), expected); @@ -77,12 +91,12 @@ describe("ServiceClient", function () { let request: WebResourceLike; const client = new ServiceClient(undefined, { httpClient: { - sendRequest: req => { + sendRequest: (req) => { request = req; return Promise.resolve({ request, status: 200, headers: new HttpHeaders() }); - } + }, }, - requestPolicyFactories: [] + requestPolicyFactories: [], }); const response = await client.sendOperationRequest( @@ -93,64 +107,130 @@ describe("ServiceClient", function () { serializer: new Serializer(), headerParameters: [], responses: { - 200: {} - } - }); + 200: {}, + }, + } + ); assert(request!); assert.strictEqual(JSON.stringify(response), "{}"); }); - it("should serialize collection:csv query parameters", async function() { + it("should serialize collection:csv query parameters", async function () { await testSendOperationRequest(["1", "2", "3"], QueryCollectionFormat.Csv, false, "?q=1,2,3"); }); - it("should serialize collection:csv query parameters with commas & skipEncoding true", async function() { - await testSendOperationRequest(["1,2", "3,4", "5"], QueryCollectionFormat.Csv, true, "?q=1,2,3,4,5"); + it("should serialize collection:csv query parameters with commas & skipEncoding true", async function () { + await testSendOperationRequest( + ["1,2", "3,4", "5"], + QueryCollectionFormat.Csv, + true, + "?q=1,2,3,4,5" + ); }); - it("should serialize collection:csv query parameters with commas", async function() { - await testSendOperationRequest(["1,2", "3,4", "5"], QueryCollectionFormat.Csv, false, "?q=1%2C2,3%2C4,5"); + it("should serialize collection:csv query parameters with commas", async function () { + await testSendOperationRequest( + ["1,2", "3,4", "5"], + QueryCollectionFormat.Csv, + false, + "?q=1%2C2,3%2C4,5" + ); }); - it("should serialize collection:csv query parameters with undefined and null", async function() { - await testSendOperationRequest(["1,2", undefined, "5"], QueryCollectionFormat.Csv, false, "?q=1%2C2,,5"); - /* tslint:disable-next-line:no-null-keyword */ - await testSendOperationRequest(["1,2", null, "5"], QueryCollectionFormat.Csv, false, "?q=1%2C2,,5"); + it("should serialize collection:csv query parameters with undefined and null", async function () { + await testSendOperationRequest( + ["1,2", undefined, "5"], + QueryCollectionFormat.Csv, + false, + "?q=1%2C2,,5" + ); + await testSendOperationRequest( + /* tslint:disable-next-line:no-null-keyword */ + ["1,2", null, "5"], + QueryCollectionFormat.Csv, + false, + "?q=1%2C2,,5" + ); }); - it("should serialize collection:tsv query parameters with undefined and null", async function() { - await testSendOperationRequest(["1,2", undefined, "5"], QueryCollectionFormat.Tsv, false, "?q=1%2C2%09%095"); - /* tslint:disable-next-line:no-null-keyword */ - await testSendOperationRequest(["1,2", null, "5"], QueryCollectionFormat.Tsv, false, "?q=1%2C2%09%095"); - await testSendOperationRequest(["1,2", "3", "5"], QueryCollectionFormat.Tsv, false, "?q=1%2C2%093%095"); + it("should serialize collection:tsv query parameters with undefined and null", async function () { + await testSendOperationRequest( + ["1,2", undefined, "5"], + QueryCollectionFormat.Tsv, + false, + "?q=1%2C2%09%095" + ); + await testSendOperationRequest( + /* tslint:disable-next-line:no-null-keyword */ + ["1,2", null, "5"], + QueryCollectionFormat.Tsv, + false, + "?q=1%2C2%09%095" + ); + await testSendOperationRequest( + ["1,2", "3", "5"], + QueryCollectionFormat.Tsv, + false, + "?q=1%2C2%093%095" + ); }); - it("should serialize collection:ssv query parameters with undefined and null", async function() { - await testSendOperationRequest(["1,2", undefined, "5"], QueryCollectionFormat.Ssv, false, "?q=1%2C2%20%205"); - /* tslint:disable-next-line:no-null-keyword */ - await testSendOperationRequest(["1,2", null, "5"], QueryCollectionFormat.Ssv, false, "?q=1%2C2%20%205"); - await testSendOperationRequest(["1,2", "3", "5"], QueryCollectionFormat.Ssv, false, "?q=1%2C2%203%205"); + it("should serialize collection:ssv query parameters with undefined and null", async function () { + await testSendOperationRequest( + ["1,2", undefined, "5"], + QueryCollectionFormat.Ssv, + false, + "?q=1%2C2%20%205" + ); + await testSendOperationRequest( + /* tslint:disable-next-line:no-null-keyword */ + ["1,2", null, "5"], + QueryCollectionFormat.Ssv, + false, + "?q=1%2C2%20%205" + ); + await testSendOperationRequest( + ["1,2", "3", "5"], + QueryCollectionFormat.Ssv, + false, + "?q=1%2C2%203%205" + ); }); it("should serialize collection:multi query parameters", async function () { - await testSendOperationRequest(["1", "2", "3"], QueryCollectionFormat.Multi, false, "?q=1&q=2&q=3"); - await testSendOperationRequest(["1,2", "3,4", "5"], QueryCollectionFormat.Multi, false, "?q=1%2C2&q=3%2C4&q=5"); - await testSendOperationRequest(["1,2", "3,4", "5"], QueryCollectionFormat.Multi, true, "?q=1,2&q=3,4&q=5"); + await testSendOperationRequest( + ["1", "2", "3"], + QueryCollectionFormat.Multi, + false, + "?q=1&q=2&q=3" + ); + await testSendOperationRequest( + ["1,2", "3,4", "5"], + QueryCollectionFormat.Multi, + false, + "?q=1%2C2&q=3%2C4&q=5" + ); + await testSendOperationRequest( + ["1,2", "3,4", "5"], + QueryCollectionFormat.Multi, + true, + "?q=1,2&q=3,4&q=5" + ); }); it("should apply withCredentials to requests", async function () { let request: WebResourceLike; const httpClient: HttpClient = { - sendRequest: req => { + sendRequest: (req) => { request = req; return Promise.resolve({ request, status: 200, headers: new HttpHeaders() }); - } + }, }; const client1 = new ServiceClient(undefined, { httpClient, - requestPolicyFactories: () => [] + requestPolicyFactories: () => [], }); await client1.sendOperationRequest( {}, @@ -158,15 +238,16 @@ describe("ServiceClient", function () { serializer: new Serializer(), httpMethod: "GET", baseUrl: "httpbin.org", - responses: { 200: {} } - }); + responses: { 200: {} }, + } + ); assert.strictEqual(request!.withCredentials, false); const client2 = new ServiceClient(undefined, { httpClient, requestPolicyFactories: [], - withCredentials: true + withCredentials: true, }); await client2.sendOperationRequest( {}, @@ -174,23 +255,29 @@ describe("ServiceClient", function () { serializer: new Serializer(), httpMethod: "GET", baseUrl: "httpbin.org", - responses: { 200: {} } - }); + responses: { 200: {} }, + } + ); assert.strictEqual(request!.withCredentials, true); }); it("should deserialize response bodies", async function () { let request: WebResourceLike; const httpClient: HttpClient = { - sendRequest: req => { + sendRequest: (req) => { request = req; - return Promise.resolve({ request, status: 200, headers: new HttpHeaders(), bodyAsText: "[1,2,3]" }); - } + return Promise.resolve({ + request, + status: 200, + headers: new HttpHeaders(), + bodyAsText: "[1,2,3]", + }); + }, }; const client1 = new ServiceClient(undefined, { httpClient, - requestPolicyFactories: [deserializationPolicy()] + requestPolicyFactories: [deserializationPolicy()], }); const res = await client1.sendOperationRequest( @@ -206,14 +293,15 @@ describe("ServiceClient", function () { name: "Sequence", element: { type: { - name: "Number" - } - } - } - } - } - } - }); + name: "Number", + }, + }, + }, + }, + }, + }, + } + ); assert.strictEqual(res._response.status, 200); assert.deepStrictEqual(res.slice(), [1, 2, 3]); @@ -296,13 +384,13 @@ describe("ServiceClient", function () { const httpClient: HttpClient = { sendRequest: (request: WebResourceLike) => { return Promise.resolve({ request, status: 200, headers: new HttpHeaders() }); - } + }, }; const client1 = new ServiceClient(undefined, { httpClient, userAgentHeaderName: "my-user-agent-key", - userAgent: "blah blah" + userAgent: "blah blah", }); const response: RestResponse = await client1.sendOperationRequest( @@ -311,8 +399,9 @@ describe("ServiceClient", function () { serializer: new Serializer(), httpMethod: "GET", baseUrl: "httpbin.org", - responses: {} - }); + responses: {}, + } + ); assert.strictEqual(response._response.status, 200); assert.strictEqual(response._response.request.headers.get("my-user-agent-key"), "blah blah"); @@ -322,13 +411,13 @@ describe("ServiceClient", function () { const httpClient: HttpClient = { sendRequest: (request: WebResourceLike) => { return Promise.resolve({ request, status: 200, headers: new HttpHeaders() }); - } + }, }; const client1 = new ServiceClient(undefined, { httpClient, userAgentHeaderName: () => "my-user-agent-key-2", - userAgent: "blah blah" + userAgent: "blah blah", }); const response: RestResponse = await client1.sendOperationRequest( @@ -337,8 +426,9 @@ describe("ServiceClient", function () { serializer: new Serializer(), httpMethod: "GET", baseUrl: "httpbin.org", - responses: {} - }); + responses: {}, + } + ); assert.strictEqual(response._response.status, 200); assert.strictEqual(response._response.request.headers.get("my-user-agent-key-2"), "blah blah"); @@ -348,12 +438,12 @@ describe("ServiceClient", function () { const httpClient: HttpClient = { sendRequest: (request: WebResourceLike) => { return Promise.resolve({ request, status: 200, headers: new HttpHeaders() }); - } + }, }; const client1 = new ServiceClient(undefined, { httpClient, - userAgent: "blah blah" + userAgent: "blah blah", }); const response: RestResponse = await client1.sendOperationRequest( @@ -362,23 +452,27 @@ describe("ServiceClient", function () { serializer: new Serializer(), httpMethod: "GET", baseUrl: "httpbin.org", - responses: {} - }); + responses: {}, + } + ); assert.strictEqual(response._response.status, 200); - assert.strictEqual(response._response.request.headers.get(isNode ? "user-agent" : "x-ms-command-name"), "blah blah"); + assert.strictEqual( + response._response.request.headers.get(isNode ? "user-agent" : "x-ms-command-name"), + "blah blah" + ); }); it("should use userAgent function from options that appends to defaultUserAgent", async function () { const httpClient: HttpClient = { sendRequest: (request: WebResourceLike) => { return Promise.resolve({ request, status: 200, headers: new HttpHeaders() }); - } + }, }; const client1 = new ServiceClient(undefined, { httpClient, - userAgent: (defaultUserAgent: string) => `${defaultUserAgent}/blah blah` + userAgent: (defaultUserAgent: string) => `${defaultUserAgent}/blah blah`, }); const response: RestResponse = await client1.sendOperationRequest( @@ -387,11 +481,14 @@ describe("ServiceClient", function () { serializer: new Serializer(), httpMethod: "GET", baseUrl: "httpbin.org", - responses: {} - }); + responses: {}, + } + ); assert.strictEqual(response._response.status, 200); - const userAgentHeaderValue: string | undefined = response._response.request.headers.get(isNode ? "user-agent" : "x-ms-command-name"); + const userAgentHeaderValue: string | undefined = response._response.request.headers.get( + isNode ? "user-agent" : "x-ms-command-name" + ); assert(userAgentHeaderValue); assert(userAgentHeaderValue!.startsWith("ms-rest-js/")); assert(userAgentHeaderValue!.endsWith("/blah blah")); @@ -401,12 +498,12 @@ describe("ServiceClient", function () { const httpClient: HttpClient = { sendRequest: (request: WebResourceLike) => { return Promise.resolve({ request, status: 200, headers: new HttpHeaders() }); - } + }, }; const client1 = new ServiceClient(undefined, { httpClient, - userAgent: () => `blah blah 2` + userAgent: () => `blah blah 2`, }); const response: RestResponse = await client1.sendOperationRequest( @@ -415,11 +512,15 @@ describe("ServiceClient", function () { serializer: new Serializer(), httpMethod: "GET", baseUrl: "httpbin.org", - responses: {} - }); + responses: {}, + } + ); assert.strictEqual(response._response.status, 200); - assert.strictEqual(response._response.request.headers.get(isNode ? "user-agent" : "x-ms-command-name"), "blah blah 2"); + assert.strictEqual( + response._response.request.headers.get(isNode ? "user-agent" : "x-ms-command-name"), + "blah blah 2" + ); }); describe("serializeRequestBody()", () => { @@ -429,7 +530,7 @@ describe("ServiceClient", function () { new ServiceClient(), httpRequest, { - bodyArg: "body value" + bodyArg: "body value", }, { httpMethod: "POST", @@ -439,13 +540,14 @@ describe("ServiceClient", function () { required: true, serializedName: "bodyArg", type: { - name: MapperType.String - } - } + name: MapperType.String, + }, + }, }, responses: { 200: {} }, - serializer: new Serializer() - }); + serializer: new Serializer(), + } + ); assert.strictEqual(httpRequest.body, `"body value"`); }); @@ -455,7 +557,7 @@ describe("ServiceClient", function () { new ServiceClient(), httpRequest, { - bodyArg: stringToByteArray("Javascript") + bodyArg: stringToByteArray("Javascript"), }, { httpMethod: "POST", @@ -465,13 +567,14 @@ describe("ServiceClient", function () { required: true, serializedName: "bodyArg", type: { - name: MapperType.ByteArray - } - } + name: MapperType.ByteArray, + }, + }, }, responses: { 200: {} }, - serializer: new Serializer() - }); + serializer: new Serializer(), + } + ); assert.strictEqual(httpRequest.body, `"SmF2YXNjcmlwdA=="`); }); @@ -481,7 +584,7 @@ describe("ServiceClient", function () { new ServiceClient(), httpRequest, { - bodyArg: "body value" + bodyArg: "body value", }, { httpMethod: "POST", @@ -491,13 +594,14 @@ describe("ServiceClient", function () { required: true, serializedName: "bodyArg", type: { - name: MapperType.Stream - } - } + name: MapperType.Stream, + }, + }, }, responses: { 200: {} }, - serializer: new Serializer() - }); + serializer: new Serializer(), + } + ); assert.strictEqual(httpRequest.body, "body value"); }); @@ -507,7 +611,7 @@ describe("ServiceClient", function () { new ServiceClient(), httpRequest, { - bodyArg: "body value" + bodyArg: "body value", }, { httpMethod: "POST", @@ -517,17 +621,19 @@ describe("ServiceClient", function () { required: true, serializedName: "bodyArg", type: { - name: MapperType.String - } - } + name: MapperType.String, + }, + }, }, responses: { 200: {} }, serializer: new Serializer(), - isXML: true - }); + isXML: true, + } + ); assert.strictEqual( httpRequest.body, - `body value`); + `body value` + ); }); it("should serialize an XML ByteArray request body", () => { @@ -536,7 +642,7 @@ describe("ServiceClient", function () { new ServiceClient(), httpRequest, { - bodyArg: stringToByteArray("Javascript") + bodyArg: stringToByteArray("Javascript"), }, { httpMethod: "POST", @@ -546,17 +652,19 @@ describe("ServiceClient", function () { required: true, serializedName: "bodyArg", type: { - name: MapperType.ByteArray - } - } + name: MapperType.ByteArray, + }, + }, }, responses: { 200: {} }, serializer: new Serializer(), - isXML: true - }); + isXML: true, + } + ); assert.strictEqual( httpRequest.body, - `SmF2YXNjcmlwdA==`); + `SmF2YXNjcmlwdA==` + ); }); it("should serialize an XML Stream request body", () => { @@ -565,7 +673,7 @@ describe("ServiceClient", function () { new ServiceClient(), httpRequest, { - bodyArg: "body value" + bodyArg: "body value", }, { httpMethod: "POST", @@ -575,14 +683,15 @@ describe("ServiceClient", function () { required: true, serializedName: "bodyArg", type: { - name: MapperType.Stream - } - } + name: MapperType.Stream, + }, + }, }, responses: { 200: {} }, serializer: new Serializer(), - isXML: true - }); + isXML: true, + } + ); assert.strictEqual(httpRequest.body, "body value"); }); }); @@ -595,26 +704,38 @@ describe("ServiceClient", function () { const parameterMapper: Mapper = { serializedName: "my-parameter", type: { - name: MapperType.Number - } + name: MapperType.Number, + }, }; - const parameterValue: any = getOperationArgumentValueFromParameterPath(serviceClient, operationArguments, parameterPath, parameterMapper, new Serializer()); + const parameterValue: any = getOperationArgumentValueFromParameterPath( + serviceClient, + operationArguments, + parameterPath, + parameterMapper, + new Serializer() + ); assert.strictEqual(parameterValue, undefined); }); it("should return undefined when the parameter path is found in the operation arguments but is undefined and doesn't have a default value", () => { const serviceClient = new ServiceClient(); const operationArguments: OperationArguments = { - "myParameter": undefined + myParameter: undefined, }; const parameterPath: ParameterPath = "myParameter"; const parameterMapper: Mapper = { serializedName: "my-parameter", type: { - name: MapperType.Number - } + name: MapperType.Number, + }, }; - const parameterValue: any = getOperationArgumentValueFromParameterPath(serviceClient, operationArguments, parameterPath, parameterMapper, new Serializer()); + const parameterValue: any = getOperationArgumentValueFromParameterPath( + serviceClient, + operationArguments, + parameterPath, + parameterMapper, + new Serializer() + ); assert.strictEqual(parameterValue, undefined); }); @@ -622,16 +743,22 @@ describe("ServiceClient", function () { const serviceClient = new ServiceClient(); const operationArguments: OperationArguments = { // tslint:disable-next-line:no-null-keyword - "myParameter": null + myParameter: null, }; const parameterPath: ParameterPath = "myParameter"; const parameterMapper: Mapper = { serializedName: "my-parameter", type: { - name: MapperType.Number - } + name: MapperType.Number, + }, }; - const parameterValue: any = getOperationArgumentValueFromParameterPath(serviceClient, operationArguments, parameterPath, parameterMapper, new Serializer()); + const parameterValue: any = getOperationArgumentValueFromParameterPath( + serviceClient, + operationArguments, + parameterPath, + parameterMapper, + new Serializer() + ); // tslint:disable-next-line:no-null-keyword assert.strictEqual(parameterValue, null); }); @@ -639,34 +766,46 @@ describe("ServiceClient", function () { it("should return the operation argument value when the parameter path is found in the operation arguments", () => { const serviceClient = new ServiceClient(); const operationArguments: OperationArguments = { - "myParameter": 20 + myParameter: 20, }; const parameterPath: ParameterPath = "myParameter"; const parameterMapper: Mapper = { serializedName: "my-parameter", type: { - name: MapperType.Number - } + name: MapperType.Number, + }, }; - const parameterValue: any = getOperationArgumentValueFromParameterPath(serviceClient, operationArguments, parameterPath, parameterMapper, new Serializer()); + const parameterValue: any = getOperationArgumentValueFromParameterPath( + serviceClient, + operationArguments, + parameterPath, + parameterMapper, + new Serializer() + ); assert.strictEqual(parameterValue, 20); }); it("should return the options operation argument value when the parameter path is found in the optional operation arguments", () => { const serviceClient = new ServiceClient(); const operationArguments: OperationArguments = { - "options": { - "myParameter": 1 - } + options: { + myParameter: 1, + }, }; const parameterPath: ParameterPath = ["options", "myParameter"]; const parameterMapper: Mapper = { serializedName: "my-parameter", type: { - name: MapperType.Number - } + name: MapperType.Number, + }, }; - const parameterValue: any = getOperationArgumentValueFromParameterPath(serviceClient, operationArguments, parameterPath, parameterMapper, new Serializer()); + const parameterValue: any = getOperationArgumentValueFromParameterPath( + serviceClient, + operationArguments, + parameterPath, + parameterMapper, + new Serializer() + ); assert.strictEqual(parameterValue, 1); }); @@ -678,10 +817,16 @@ describe("ServiceClient", function () { const parameterMapper: Mapper = { serializedName: "my-parameter", type: { - name: MapperType.Number - } + name: MapperType.Number, + }, }; - const parameterValue: any = getOperationArgumentValueFromParameterPath(serviceClient, operationArguments, parameterPath, parameterMapper, new Serializer()); + const parameterValue: any = getOperationArgumentValueFromParameterPath( + serviceClient, + operationArguments, + parameterPath, + parameterMapper, + new Serializer() + ); assert.strictEqual(parameterValue, 21); }); @@ -689,16 +834,22 @@ describe("ServiceClient", function () { const serviceClient = new ServiceClient(); (serviceClient as any)["myParameter"] = 21; const operationArguments: OperationArguments = { - "myParameter": 22 + myParameter: 22, }; const parameterPath: ParameterPath = "myParameter"; const parameterMapper: Mapper = { serializedName: "my-parameter", type: { - name: MapperType.Number - } + name: MapperType.Number, + }, }; - const parameterValue: any = getOperationArgumentValueFromParameterPath(serviceClient, operationArguments, parameterPath, parameterMapper, new Serializer()); + const parameterValue: any = getOperationArgumentValueFromParameterPath( + serviceClient, + operationArguments, + parameterPath, + parameterMapper, + new Serializer() + ); assert.strictEqual(parameterValue, 22); }); @@ -711,10 +862,16 @@ describe("ServiceClient", function () { isConstant: true, defaultValue: 1, type: { - name: MapperType.Number - } + name: MapperType.Number, + }, }; - const parameterValue: any = getOperationArgumentValueFromParameterPath(serviceClient, operationArguments, parameterPath, parameterMapper, new Serializer()); + const parameterValue: any = getOperationArgumentValueFromParameterPath( + serviceClient, + operationArguments, + parameterPath, + parameterMapper, + new Serializer() + ); assert.strictEqual(parameterValue, 1); }); @@ -722,10 +879,10 @@ describe("ServiceClient", function () { const serviceClient = new ServiceClient(); (serviceClient as any)["myParameter"] = 1; const operationArguments: OperationArguments = { - "myParameter": 2, - "options": { - "myParameter": 3 - } + myParameter: 2, + options: { + myParameter: 3, + }, }; const parameterPath: ParameterPath = "myParameter"; const parameterMapper: Mapper = { @@ -733,10 +890,16 @@ describe("ServiceClient", function () { isConstant: true, defaultValue: 4, type: { - name: MapperType.Number - } + name: MapperType.Number, + }, }; - const parameterValue: any = getOperationArgumentValueFromParameterPath(serviceClient, operationArguments, parameterPath, parameterMapper, new Serializer()); + const parameterValue: any = getOperationArgumentValueFromParameterPath( + serviceClient, + operationArguments, + parameterPath, + parameterMapper, + new Serializer() + ); assert.strictEqual(parameterValue, 4); }); @@ -748,10 +911,16 @@ describe("ServiceClient", function () { serializedName: "my-parameter", defaultValue: 21, type: { - name: MapperType.Number - } + name: MapperType.Number, + }, }; - const parameterValue: any = getOperationArgumentValueFromParameterPath(serviceClient, operationArguments, parameterPath, parameterMapper, new Serializer()); + const parameterValue: any = getOperationArgumentValueFromParameterPath( + serviceClient, + operationArguments, + parameterPath, + parameterMapper, + new Serializer() + ); assert.strictEqual(parameterValue, undefined); }); @@ -764,19 +933,25 @@ describe("ServiceClient", function () { defaultValue: 21, required: true, type: { - name: MapperType.Number - } + name: MapperType.Number, + }, }; - const parameterValue: any = getOperationArgumentValueFromParameterPath(serviceClient, operationArguments, parameterPath, parameterMapper, new Serializer()); + const parameterValue: any = getOperationArgumentValueFromParameterPath( + serviceClient, + operationArguments, + parameterPath, + parameterMapper, + new Serializer() + ); assert.strictEqual(parameterValue, 21); }); it("should return the default value when the parameter path is partially found in the operation arguments, the parameter is required, and it has a default value", () => { const serviceClient = new ServiceClient(); const operationArguments: OperationArguments = { - "myParameter": { - "differentProperty": "hello" - } + myParameter: { + differentProperty: "hello", + }, }; const parameterPath: ParameterPath = ["myParameter", "myProperty"]; const parameterMapper: Mapper = { @@ -784,29 +959,41 @@ describe("ServiceClient", function () { defaultValue: 21, required: true, type: { - name: MapperType.Number - } + name: MapperType.Number, + }, }; - const parameterValue: any = getOperationArgumentValueFromParameterPath(serviceClient, operationArguments, parameterPath, parameterMapper, new Serializer()); + const parameterValue: any = getOperationArgumentValueFromParameterPath( + serviceClient, + operationArguments, + parameterPath, + parameterMapper, + new Serializer() + ); assert.strictEqual(parameterValue, 21); }); it("should return undefined when the parameter path is partially found in the operation arguments, the parameter is optional, and it has a default value", () => { const serviceClient = new ServiceClient(); const operationArguments: OperationArguments = { - "myParameter": { - "differentProperty": "hello" - } + myParameter: { + differentProperty: "hello", + }, }; const parameterPath: ParameterPath = ["myParameter", "myProperty"]; const parameterMapper: Mapper = { serializedName: "my-parameter", defaultValue: 21, type: { - name: MapperType.Number - } + name: MapperType.Number, + }, }; - const parameterValue: any = getOperationArgumentValueFromParameterPath(serviceClient, operationArguments, parameterPath, parameterMapper, new Serializer()); + const parameterValue: any = getOperationArgumentValueFromParameterPath( + serviceClient, + operationArguments, + parameterPath, + parameterMapper, + new Serializer() + ); assert.strictEqual(parameterValue, undefined); }); @@ -818,10 +1005,16 @@ describe("ServiceClient", function () { serializedName: "my-parameter", defaultValue: 21, type: { - name: MapperType.Number - } + name: MapperType.Number, + }, }; - const parameterValue: any = getOperationArgumentValueFromParameterPath(serviceClient, operationArguments, parameterPath, parameterMapper, new Serializer()); + const parameterValue: any = getOperationArgumentValueFromParameterPath( + serviceClient, + operationArguments, + parameterPath, + parameterMapper, + new Serializer() + ); assert.strictEqual(parameterValue, 21); }); @@ -833,10 +1026,16 @@ describe("ServiceClient", function () { serializedName: "my-parameter", defaultValue: 21, type: { - name: MapperType.Number - } + name: MapperType.Number, + }, }; - const parameterValue: any = getOperationArgumentValueFromParameterPath(serviceClient, operationArguments, parameterPath, parameterMapper, new Serializer()); + const parameterValue: any = getOperationArgumentValueFromParameterPath( + serviceClient, + operationArguments, + parameterPath, + parameterMapper, + new Serializer() + ); assert.strictEqual(parameterValue, undefined); }); @@ -844,17 +1043,23 @@ describe("ServiceClient", function () { const serviceClient = new ServiceClient(); const operationArguments: OperationArguments = { // tslint:disable-next-line:no-null-keyword - "myParameter": null + myParameter: null, }; const parameterPath: ParameterPath = "myParameter"; const parameterMapper: Mapper = { serializedName: "my-parameter", defaultValue: 2, type: { - name: MapperType.Number - } + name: MapperType.Number, + }, }; - const parameterValue: any = getOperationArgumentValueFromParameterPath(serviceClient, operationArguments, parameterPath, parameterMapper, new Serializer()); + const parameterValue: any = getOperationArgumentValueFromParameterPath( + serviceClient, + operationArguments, + parameterPath, + parameterMapper, + new Serializer() + ); // tslint:disable-next-line:no-null-keyword assert.strictEqual(parameterValue, null); }); @@ -868,10 +1073,16 @@ describe("ServiceClient", function () { serializedName: "my-parameter", defaultValue: 2, type: { - name: MapperType.Number - } + name: MapperType.Number, + }, }; - const parameterValue: any = getOperationArgumentValueFromParameterPath(serviceClient, operationArguments, parameterPath, parameterMapper, new Serializer()); + const parameterValue: any = getOperationArgumentValueFromParameterPath( + serviceClient, + operationArguments, + parameterPath, + parameterMapper, + new Serializer() + ); // tslint:disable-next-line:no-null-keyword assert.strictEqual(parameterValue, 5); }); @@ -886,11 +1097,16 @@ function stringToByteArray(str: string): Uint8Array { } } -async function testSendOperationRequest(queryValue: any, queryCollectionFormat: QueryCollectionFormat, skipEncodingParameter: boolean, expected: string) { +async function testSendOperationRequest( + queryValue: any, + queryCollectionFormat: QueryCollectionFormat, + skipEncodingParameter: boolean, + expected: string +) { let request: WebResourceLike; const client = new ServiceClient(undefined, { httpClient: { - sendRequest: req => { + sendRequest: (req) => { request = req; return Promise.resolve({ request, status: 200, headers: new HttpHeaders() }); }, @@ -900,7 +1116,7 @@ async function testSendOperationRequest(queryValue: any, queryCollectionFormat: await client.sendOperationRequest( { - q: queryValue + q: queryValue, }, { httpMethod: "GET", @@ -933,4 +1149,4 @@ async function testSendOperationRequest(queryValue: any, queryCollectionFormat: assert(request!); assert(request!.url.endsWith(expected), `"${request!.url}" does not end with "${expected}"`); -} \ No newline at end of file +} diff --git a/test/urlTests.ts b/test/urlTests.ts index 947c19e..b9af168 100644 --- a/test/urlTests.ts +++ b/test/urlTests.ts @@ -109,23 +109,32 @@ describe("URLQuery", () => { }); it(`parse with base64 token as last parameter`, () => { - const expectedValue = "ODIzZnNkdi01YXNjLTEzc2EtMTI1NS1jYTNhc2QxMmRhMyEvU3Vic2NyaXB0aW9ucy8xMTExMTEtMTExMS0xMTExLTExMTEtMTExMTExMTExL1Jlc291cmNlR3JvdXBzL0FFLVdPUktFUlMvVk1TY2FsZVNldHMvQUUtV09SS0VSUy1TQ0FMRS0xMDAwL1ZNcy8xNDMz=="; - const parsedURL = URLQuery.parse("?api-version=2020-06-01&bas64Value=ODIzZnNkdi01YXNjLTEzc2EtMTI1NS1jYTNhc2QxMmRhMyEvU3Vic2NyaXB0aW9ucy8xMTExMTEtMTExMS0xMTExLTExMTEtMTExMTExMTExL1Jlc291cmNlR3JvdXBzL0FFLVdPUktFUlMvVk1TY2FsZVNldHMvQUUtV09SS0VSUy1TQ0FMRS0xMDAwL1ZNcy8xNDMz=="); + const expectedValue = + "ODIzZnNkdi01YXNjLTEzc2EtMTI1NS1jYTNhc2QxMmRhMyEvU3Vic2NyaXB0aW9ucy8xMTExMTEtMTExMS0xMTExLTExMTEtMTExMTExMTExL1Jlc291cmNlR3JvdXBzL0FFLVdPUktFUlMvVk1TY2FsZVNldHMvQUUtV09SS0VSUy1TQ0FMRS0xMDAwL1ZNcy8xNDMz=="; + const parsedURL = URLQuery.parse( + "?api-version=2020-06-01&bas64Value=ODIzZnNkdi01YXNjLTEzc2EtMTI1NS1jYTNhc2QxMmRhMyEvU3Vic2NyaXB0aW9ucy8xMTExMTEtMTExMS0xMTExLTExMTEtMTExMTExMTExL1Jlc291cmNlR3JvdXBzL0FFLVdPUktFUlMvVk1TY2FsZVNldHMvQUUtV09SS0VSUy1TQ0FMRS0xMDAwL1ZNcy8xNDMz==" + ); assert.strictEqual(parsedURL.get("bas64Value"), expectedValue); assert.strictEqual(parsedURL.get("api-version"), "2020-06-01"); }); it(`parse with base64 token as middle parameter`, () => { - const expectedValue = "ODIzZnNkdi01YXNjLTEzc2EtMTI1NS1jYTNhc2QxMmRhMyEvU3Vic2NyaXB0aW9ucy8xMTExMTEtMTExMS0xMTExLTExMTEtMTExMTExMTExL1Jlc291cmNlR3JvdXBzL0FFLVdPUktFUlMvVk1TY2FsZVNldHMvQUUtV09SS0VSUy1TQ0FMRS0xMDAwL1ZNcy8xNDMz=="; - const parsedURL = URLQuery.parse("?api-version=2020-06-01&bas64Value=ODIzZnNkdi01YXNjLTEzc2EtMTI1NS1jYTNhc2QxMmRhMyEvU3Vic2NyaXB0aW9ucy8xMTExMTEtMTExMS0xMTExLTExMTEtMTExMTExMTExL1Jlc291cmNlR3JvdXBzL0FFLVdPUktFUlMvVk1TY2FsZVNldHMvQUUtV09SS0VSUy1TQ0FMRS0xMDAwL1ZNcy8xNDMz==&extraParam=foo"); + const expectedValue = + "ODIzZnNkdi01YXNjLTEzc2EtMTI1NS1jYTNhc2QxMmRhMyEvU3Vic2NyaXB0aW9ucy8xMTExMTEtMTExMS0xMTExLTExMTEtMTExMTExMTExL1Jlc291cmNlR3JvdXBzL0FFLVdPUktFUlMvVk1TY2FsZVNldHMvQUUtV09SS0VSUy1TQ0FMRS0xMDAwL1ZNcy8xNDMz=="; + const parsedURL = URLQuery.parse( + "?api-version=2020-06-01&bas64Value=ODIzZnNkdi01YXNjLTEzc2EtMTI1NS1jYTNhc2QxMmRhMyEvU3Vic2NyaXB0aW9ucy8xMTExMTEtMTExMS0xMTExLTExMTEtMTExMTExMTExL1Jlc291cmNlR3JvdXBzL0FFLVdPUktFUlMvVk1TY2FsZVNldHMvQUUtV09SS0VSUy1TQ0FMRS0xMDAwL1ZNcy8xNDMz==&extraParam=foo" + ); assert.strictEqual(parsedURL.get("bas64Value"), expectedValue); assert.strictEqual(parsedURL.get("api-version"), "2020-06-01"); assert.strictEqual(parsedURL.get("extraParam"), "foo"); }); it(`parse with base64 token as first parameter`, () => { - const expectedValue = "ODIzZnNkdi01YXNjLTEzc2EtMTI1NS1jYTNhc2QxMmRhMyEvU3Vic2NyaXB0aW9ucy8xMTExMTEtMTExMS0xMTExLTExMTEtMTExMTExMTExL1Jlc291cmNlR3JvdXBzL0FFLVdPUktFUlMvVk1TY2FsZVNldHMvQUUtV09SS0VSUy1TQ0FMRS0xMDAwL1ZNcy8xNDMz=="; - const parsedURL = URLQuery.parse("?bas64Value=ODIzZnNkdi01YXNjLTEzc2EtMTI1NS1jYTNhc2QxMmRhMyEvU3Vic2NyaXB0aW9ucy8xMTExMTEtMTExMS0xMTExLTExMTEtMTExMTExMTExL1Jlc291cmNlR3JvdXBzL0FFLVdPUktFUlMvVk1TY2FsZVNldHMvQUUtV09SS0VSUy1TQ0FMRS0xMDAwL1ZNcy8xNDMz==&api-version=2020-06-01"); + const expectedValue = + "ODIzZnNkdi01YXNjLTEzc2EtMTI1NS1jYTNhc2QxMmRhMyEvU3Vic2NyaXB0aW9ucy8xMTExMTEtMTExMS0xMTExLTExMTEtMTExMTExMTExL1Jlc291cmNlR3JvdXBzL0FFLVdPUktFUlMvVk1TY2FsZVNldHMvQUUtV09SS0VSUy1TQ0FMRS0xMDAwL1ZNcy8xNDMz=="; + const parsedURL = URLQuery.parse( + "?bas64Value=ODIzZnNkdi01YXNjLTEzc2EtMTI1NS1jYTNhc2QxMmRhMyEvU3Vic2NyaXB0aW9ucy8xMTExMTEtMTExMS0xMTExLTExMTEtMTExMTExMTExL1Jlc291cmNlR3JvdXBzL0FFLVdPUktFUlMvVk1TY2FsZVNldHMvQUUtV09SS0VSUy1TQ0FMRS0xMDAwL1ZNcy8xNDMz==&api-version=2020-06-01" + ); assert.strictEqual(parsedURL.get("bas64Value"), expectedValue); assert.strictEqual(parsedURL.get("api-version"), "2020-06-01"); }); @@ -283,7 +292,10 @@ describe("URLBuilder", () => { assert.strictEqual(urlBuilder.getScheme(), "https"); assert.strictEqual(urlBuilder.getHost(), "www.example.com"); assert.strictEqual(urlBuilder.getPath(), "mypath"); - assert.strictEqual(urlBuilder.toString(), "https://www.example.com/mypath?thing=stuff&otherthing=otherstuff"); + assert.strictEqual( + urlBuilder.toString(), + "https://www.example.com/mypath?thing=stuff&otherthing=otherstuff" + ); }); it(`to "https" and setHost() to "www.example.com" and setPath() to "http://www.othersite.com/mypath?thing=stuff" and setQueryParameter() to "otherthing=otherstuff"`, () => { @@ -294,7 +306,10 @@ describe("URLBuilder", () => { urlBuilder.setQueryParameter("otherthing", "otherstuff"); assert.strictEqual(urlBuilder.getScheme(), "http"); assert.strictEqual(urlBuilder.getPath(), "/mypath"); - assert.strictEqual(urlBuilder.toString(), "http://www.othersite.com/mypath?thing=stuff&otherthing=otherstuff"); + assert.strictEqual( + urlBuilder.toString(), + "http://www.othersite.com/mypath?thing=stuff&otherthing=otherstuff" + ); }); }); @@ -831,23 +846,38 @@ describe("URLBuilder", () => { }); it(`with "ftp://www.bing.com:8080"`, () => { - assert.strictEqual(URLBuilder.parse("ftp://www.bing.com:8080").toString(), "ftp://www.bing.com:8080"); + assert.strictEqual( + URLBuilder.parse("ftp://www.bing.com:8080").toString(), + "ftp://www.bing.com:8080" + ); }); it(`with "www.bing.com/my/path"`, () => { - assert.strictEqual(URLBuilder.parse("www.bing.com/my/path").toString(), "www.bing.com/my/path"); + assert.strictEqual( + URLBuilder.parse("www.bing.com/my/path").toString(), + "www.bing.com/my/path" + ); }); it(`with "ftp://www.bing.com/my/path"`, () => { - assert.strictEqual(URLBuilder.parse("ftp://www.bing.com/my/path").toString(), "ftp://www.bing.com/my/path"); + assert.strictEqual( + URLBuilder.parse("ftp://www.bing.com/my/path").toString(), + "ftp://www.bing.com/my/path" + ); }); it(`with "www.bing.com:1234/my/path"`, () => { - assert.strictEqual(URLBuilder.parse("www.bing.com:1234/my/path").toString(), "www.bing.com:1234/my/path"); + assert.strictEqual( + URLBuilder.parse("www.bing.com:1234/my/path").toString(), + "www.bing.com:1234/my/path" + ); }); it(`with "ftp://www.bing.com:1234/my/path"`, () => { - assert.strictEqual(URLBuilder.parse("ftp://www.bing.com:1234/my/path").toString(), "ftp://www.bing.com:1234/my/path"); + assert.strictEqual( + URLBuilder.parse("ftp://www.bing.com:1234/my/path").toString(), + "ftp://www.bing.com:1234/my/path" + ); }); it(`with "www.bing.com?a=1"`, () => { @@ -855,67 +885,115 @@ describe("URLBuilder", () => { }); it(`with "https://www.bing.com?a=1"`, () => { - assert.strictEqual(URLBuilder.parse("https://www.bing.com?a=1").toString(), "https://www.bing.com?a=1"); + assert.strictEqual( + URLBuilder.parse("https://www.bing.com?a=1").toString(), + "https://www.bing.com?a=1" + ); }); it(`with "www.bing.com:123?a=1"`, () => { - assert.strictEqual(URLBuilder.parse("www.bing.com:123?a=1").toString(), "www.bing.com:123?a=1"); + assert.strictEqual( + URLBuilder.parse("www.bing.com:123?a=1").toString(), + "www.bing.com:123?a=1" + ); }); it(`with "https://www.bing.com:987?a=1"`, () => { - assert.strictEqual(URLBuilder.parse("https://www.bing.com:987?a=1").toString(), "https://www.bing.com:987?a=1"); + assert.strictEqual( + URLBuilder.parse("https://www.bing.com:987?a=1").toString(), + "https://www.bing.com:987?a=1" + ); }); it(`with "www.bing.com/folder/index.html?a=1"`, () => { - assert.strictEqual(URLBuilder.parse("www.bing.com/folder/index.html?a=1").toString(), "www.bing.com/folder/index.html?a=1"); + assert.strictEqual( + URLBuilder.parse("www.bing.com/folder/index.html?a=1").toString(), + "www.bing.com/folder/index.html?a=1" + ); }); it(`with "https://www.bing.com/image.gif?a=1"`, () => { - assert.strictEqual(URLBuilder.parse("https://www.bing.com/image.gif?a=1").toString(), "https://www.bing.com/image.gif?a=1"); + assert.strictEqual( + URLBuilder.parse("https://www.bing.com/image.gif?a=1").toString(), + "https://www.bing.com/image.gif?a=1" + ); }); it(`with "www.bing.com:123/index.html?a=1"`, () => { - assert.strictEqual(URLBuilder.parse("www.bing.com:123/index.html?a=1").toString(), "www.bing.com:123/index.html?a=1"); + assert.strictEqual( + URLBuilder.parse("www.bing.com:123/index.html?a=1").toString(), + "www.bing.com:123/index.html?a=1" + ); }); it(`with "https://www.bing.com:987/my/path/again?a=1"`, () => { - assert.strictEqual(URLBuilder.parse("https://www.bing.com:987/my/path/again?a=1").toString(), "https://www.bing.com:987/my/path/again?a=1"); + assert.strictEqual( + URLBuilder.parse("https://www.bing.com:987/my/path/again?a=1").toString(), + "https://www.bing.com:987/my/path/again?a=1" + ); }); it(`with "www.bing.com?a=1&b=2"`, () => { - assert.strictEqual(URLBuilder.parse("www.bing.com?a=1&b=2").toString(), "www.bing.com?a=1&b=2"); + assert.strictEqual( + URLBuilder.parse("www.bing.com?a=1&b=2").toString(), + "www.bing.com?a=1&b=2" + ); }); it(`with "https://www.bing.com?a=1&b=2"`, () => { - assert.strictEqual(URLBuilder.parse("https://www.bing.com?a=1&b=2").toString(), "https://www.bing.com?a=1&b=2"); + assert.strictEqual( + URLBuilder.parse("https://www.bing.com?a=1&b=2").toString(), + "https://www.bing.com?a=1&b=2" + ); }); it(`with "www.bing.com:123?a=1&b=2"`, () => { - assert.strictEqual(URLBuilder.parse("www.bing.com:123?a=1&b=2").toString(), "www.bing.com:123?a=1&b=2"); + assert.strictEqual( + URLBuilder.parse("www.bing.com:123?a=1&b=2").toString(), + "www.bing.com:123?a=1&b=2" + ); }); it(`with "https://www.bing.com:987?a=1&b=2"`, () => { - assert.strictEqual(URLBuilder.parse("https://www.bing.com:987?a=1&b=2").toString(), "https://www.bing.com:987?a=1&b=2"); + assert.strictEqual( + URLBuilder.parse("https://www.bing.com:987?a=1&b=2").toString(), + "https://www.bing.com:987?a=1&b=2" + ); }); it(`with "www.bing.com/folder/index.html?a=1&b=2"`, () => { - assert.strictEqual(URLBuilder.parse("www.bing.com/folder/index.html?a=1&b=2").toString(), "www.bing.com/folder/index.html?a=1&b=2"); + assert.strictEqual( + URLBuilder.parse("www.bing.com/folder/index.html?a=1&b=2").toString(), + "www.bing.com/folder/index.html?a=1&b=2" + ); }); it(`with "https://www.bing.com/image.gif?a=1&b=2"`, () => { - assert.strictEqual(URLBuilder.parse("https://www.bing.com/image.gif?a=1&b=2").toString(), "https://www.bing.com/image.gif?a=1&b=2"); + assert.strictEqual( + URLBuilder.parse("https://www.bing.com/image.gif?a=1&b=2").toString(), + "https://www.bing.com/image.gif?a=1&b=2" + ); }); it(`with "www.bing.com:123/index.html?a=1&b=2"`, () => { - assert.strictEqual(URLBuilder.parse("www.bing.com:123/index.html?a=1&b=2").toString(), "www.bing.com:123/index.html?a=1&b=2"); + assert.strictEqual( + URLBuilder.parse("www.bing.com:123/index.html?a=1&b=2").toString(), + "www.bing.com:123/index.html?a=1&b=2" + ); }); it(`with "https://www.bing.com:987/my/path/again?a=1&b=2"`, () => { - assert.strictEqual(URLBuilder.parse("https://www.bing.com:987/my/path/again?a=1&b=2").toString(), "https://www.bing.com:987/my/path/again?a=1&b=2"); + assert.strictEqual( + URLBuilder.parse("https://www.bing.com:987/my/path/again?a=1&b=2").toString(), + "https://www.bing.com:987/my/path/again?a=1&b=2" + ); }); it(`with "https://www.bing.com/my:/path"`, () => { - assert.strictEqual(URLBuilder.parse("https://www.bing.com/my:/path").toString(), "https://www.bing.com/my:/path"); + assert.strictEqual( + URLBuilder.parse("https://www.bing.com/my:/path").toString(), + "https://www.bing.com/my:/path" + ); }); }); @@ -1005,12 +1083,30 @@ describe("URLTokenizer", () => { const tokenizer = new URLTokenizer(text); if (expectedURLTokens) { for (let i = 0; i < expectedURLTokens.length; ++i) { - assert.strictEqual(tokenizer.next(), true, `Expected to find ${expectedURLTokens.length} URLTokens, but found ${i} instead.`); - assert.deepEqual(tokenizer.current(), expectedURLTokens[i], `Expected the ${i + 1} URLToken to be ${JSON.stringify(expectedURLTokens[i])}, but found ${JSON.stringify(tokenizer.current())} instead.`); + assert.strictEqual( + tokenizer.next(), + true, + `Expected to find ${expectedURLTokens.length} URLTokens, but found ${i} instead.` + ); + assert.deepEqual( + tokenizer.current(), + expectedURLTokens[i], + `Expected the ${i + 1} URLToken to be ${JSON.stringify( + expectedURLTokens[i] + )}, but found ${JSON.stringify(tokenizer.current())} instead.` + ); } } - assert.strictEqual(tokenizer.next(), false, `Only expected to find ${(expectedURLTokens ? expectedURLTokens.length : 0)} URL token(s).`); - assert.strictEqual(tokenizer.current(), undefined, `After reading all of the URLTokens, expected the current value to be undefined.`); + assert.strictEqual( + tokenizer.next(), + false, + `Only expected to find ${expectedURLTokens ? expectedURLTokens.length : 0} URL token(s).` + ); + assert.strictEqual( + tokenizer.current(), + undefined, + `After reading all of the URLTokens, expected the current value to be undefined.` + ); } it(`with ""`, () => { @@ -1018,37 +1114,25 @@ describe("URLTokenizer", () => { }); it(`with "http"`, () => { - nextTest("http", [ - URLToken.host("http") - ]); + nextTest("http", [URLToken.host("http")]); }); it(`with "http:"`, () => { - nextTest("http:", [ - URLToken.host("http"), - URLToken.port("") - ]); + nextTest("http:", [URLToken.host("http"), URLToken.port("")]); }); it(`with "http:/"`, () => { - nextTest("http:/", [ - URLToken.host("http"), - URLToken.port(""), - URLToken.path("/") - ]); + nextTest("http:/", [URLToken.host("http"), URLToken.port(""), URLToken.path("/")]); }); it(`with "http://"`, () => { - nextTest("http://", [ - URLToken.scheme("http"), - URLToken.host("") - ]); + nextTest("http://", [URLToken.scheme("http"), URLToken.host("")]); }); it(`with "https://www.example.com"`, () => { nextTest("https://www.example.com", [ URLToken.scheme("https"), - URLToken.host("www.example.com") + URLToken.host("www.example.com"), ]); }); @@ -1056,7 +1140,7 @@ describe("URLTokenizer", () => { nextTest("https://www.example.com:", [ URLToken.scheme("https"), URLToken.host("www.example.com"), - URLToken.port("") + URLToken.port(""), ]); }); @@ -1064,7 +1148,7 @@ describe("URLTokenizer", () => { nextTest("https://www.example.com:8080", [ URLToken.scheme("https"), URLToken.host("www.example.com"), - URLToken.port("8080") + URLToken.port("8080"), ]); }); @@ -1073,7 +1157,7 @@ describe("URLTokenizer", () => { URLToken.scheme("ftp"), URLToken.host("www.bing.com"), URLToken.port("123"), - URLToken.path("/") + URLToken.path("/"), ]); }); @@ -1082,7 +1166,7 @@ describe("URLTokenizer", () => { URLToken.scheme("ftp"), URLToken.host("www.bing.com"), URLToken.port("123"), - URLToken.path("/a/b/c.txt") + URLToken.path("/a/b/c.txt"), ]); }); @@ -1091,7 +1175,7 @@ describe("URLTokenizer", () => { URLToken.scheme("ftp"), URLToken.host("www.bing.com"), URLToken.port("123"), - URLToken.query("") + URLToken.query(""), ]); }); @@ -1100,7 +1184,7 @@ describe("URLTokenizer", () => { URLToken.scheme("ftp"), URLToken.host("www.bing.com"), URLToken.port("123"), - URLToken.query("a=b&c=d") + URLToken.query("a=b&c=d"), ]); }); @@ -1108,7 +1192,7 @@ describe("URLTokenizer", () => { nextTest("https://www.example.com/", [ URLToken.scheme("https"), URLToken.host("www.example.com"), - URLToken.path("/") + URLToken.path("/"), ]); }); @@ -1116,7 +1200,7 @@ describe("URLTokenizer", () => { nextTest("https://www.example.com/index.html", [ URLToken.scheme("https"), URLToken.host("www.example.com"), - URLToken.path("/index.html") + URLToken.path("/index.html"), ]); }); @@ -1125,7 +1209,7 @@ describe("URLTokenizer", () => { URLToken.scheme("https"), URLToken.host("www.example.com"), URLToken.path("/index.html"), - URLToken.query("") + URLToken.query(""), ]); }); @@ -1134,7 +1218,7 @@ describe("URLTokenizer", () => { URLToken.scheme("https"), URLToken.host("www.example.com"), URLToken.path("/index.html"), - URLToken.query("") + URLToken.query(""), ]); }); @@ -1143,7 +1227,7 @@ describe("URLTokenizer", () => { URLToken.scheme("https"), URLToken.host("www.example.com"), URLToken.path("/index.html"), - URLToken.query("alpha=beta") + URLToken.query("alpha=beta"), ]); }); @@ -1151,7 +1235,7 @@ describe("URLTokenizer", () => { nextTest("https://www.example.com?", [ URLToken.scheme("https"), URLToken.host("www.example.com"), - URLToken.query("") + URLToken.query(""), ]); }); @@ -1159,36 +1243,24 @@ describe("URLTokenizer", () => { nextTest("https://www.example.com?a=b", [ URLToken.scheme("https"), URLToken.host("www.example.com"), - URLToken.query("a=b") + URLToken.query("a=b"), ]); }); it(`with "www.test.com/"`, () => { - nextTest("www.test.com/", [ - URLToken.host("www.test.com"), - URLToken.path("/") - ]); + nextTest("www.test.com/", [URLToken.host("www.test.com"), URLToken.path("/")]); }); it(`with "www.test.com?"`, () => { - nextTest("www.test.com?", [ - URLToken.host("www.test.com"), - URLToken.query("") - ]); + nextTest("www.test.com?", [URLToken.host("www.test.com"), URLToken.query("")]); }); it(`with "folder/index.html"`, () => { - nextTest("folder/index.html", [ - URLToken.host("folder"), - URLToken.path("/index.html") - ]); + nextTest("folder/index.html", [URLToken.host("folder"), URLToken.path("/index.html")]); }); it(`with "/folder/index.html"`, () => { - nextTest("/folder/index.html", [ - URLToken.host(""), - URLToken.path("/folder/index.html") - ]); + nextTest("/folder/index.html", [URLToken.host(""), URLToken.path("/folder/index.html")]); }); }); }); diff --git a/test/xhrTests.browser.ts b/test/xhrTests.browser.ts index 7a709e2..ebec356 100644 --- a/test/xhrTests.browser.ts +++ b/test/xhrTests.browser.ts @@ -6,45 +6,47 @@ import { WebResource } from "../lib/webResource"; import { assert } from "chai"; import { parseHeaders, XhrHttpClient } from "../lib/xhrHttpClient"; -describe("XhrHttpClient", function() { - it("parses headers", function() { +describe("XhrHttpClient", function () { + it("parses headers", function () { const xhr = { - getAllResponseHeaders: () => - "Content-Length: 42\r\n" + - "value: hello\r\n" + getAllResponseHeaders: () => "Content-Length: 42\r\n" + "value: hello\r\n", } as XMLHttpRequest; const headers = parseHeaders(xhr); assert.strictEqual(headers.get("content-length"), "42"); assert.strictEqual(headers.get("value"), "hello"); }); - it("parses empty string headers", function() { + it("parses empty string headers", function () { const xhr = { getAllResponseHeaders: () => "Content-Type: \r\n" + // preserve trailing whitespace in test case - "value:\r\n" + "value:\r\n", } as XMLHttpRequest; const headers = parseHeaders(xhr); assert.strictEqual(headers.get("content-type"), ""); assert.strictEqual(headers.get("value"), ""); }); - it("throws when proxy settings are passed", function() { + it("throws when proxy settings are passed", function () { const request = new WebResource(); request.proxySettings = { host: "1.1.1.1", - port: 8080 + port: 8080, }; const client = new XhrHttpClient(); - assert.throws(() => { client.sendRequest(request); }, Error); + assert.throws(() => { + client.sendRequest(request); + }, Error); }); - it("throws when agent settings are passed", function() { + it("throws when agent settings are passed", function () { const request = new WebResource(); request.agentSettings = {} as AgentSettings; const client = new XhrHttpClient(); - assert.throws(() => { client.sendRequest(request); }, Error); + assert.throws(() => { + client.sendRequest(request); + }, Error); }); }); diff --git a/test/xmlTests.ts b/test/xmlTests.ts index 07bd67c..dc4efb0 100644 --- a/test/xmlTests.ts +++ b/test/xmlTests.ts @@ -6,13 +6,21 @@ describe("XML serializer", function () { describe("parseXML(string)", function () { it("with undefined", async function () { const error: Error = await msAssert.throwsAsync(parseXML(undefined as any)); - assert.notStrictEqual(error.message.indexOf("Document is empty"), -1, `error.message ("${error.message}") should have contained "Document is empty"`); + assert.notStrictEqual( + error.message.indexOf("Document is empty"), + -1, + `error.message ("${error.message}") should have contained "Document is empty"` + ); }); it("with null", async function () { // tslint:disable-next-line:no-null-keyword const error: Error = await msAssert.throwsAsync(parseXML(null as any)); - assert.notStrictEqual(error.message.indexOf("Document is empty"), -1, `error.message ("${error.message}") should have contained "Document is empty"`); + assert.notStrictEqual( + error.message.indexOf("Document is empty"), + -1, + `error.message ("${error.message}") should have contained "Document is empty"` + ); }); it("with empty", async function () { @@ -31,9 +39,9 @@ describe("XML serializer", function () { it("with empty element with attribute", async function () { const xml: any = await parseXML(``); assert.deepStrictEqual(xml, { - "$": { - "healthy": "true" - } + $: { + healthy: "true", + }, }); }); @@ -50,56 +58,56 @@ describe("XML serializer", function () { it("with element with attribute", async function () { const xml: any = await parseXML(``); assert.deepStrictEqual(xml, { - "$": { - "healthy": "true" - } + $: { + healthy: "true", + }, }); }); it("with element with attribute and value", async function () { const xml: any = await parseXML(`yum`); assert.deepStrictEqual(xml, { - "$": { - "healthy": "true" + $: { + healthy: "true", }, - "_": "yum" + _: "yum", }); }); it("with element with child empty element", async function () { const xml: any = await parseXML(``); assert.deepStrictEqual(xml, { - "apples": `` + apples: ``, }); }); it("with element with child empty element with attribute", async function () { const xml: any = await parseXML(``); assert.deepStrictEqual(xml, { - "apples": { - "$": { - "tasty": "true" - } - } + apples: { + $: { + tasty: "true", + }, + }, }); }); it("with element with child element with value", async function () { const xml: any = await parseXML(`yum`); assert.deepStrictEqual(xml, { - "apples": "yum" + apples: "yum", }); }); it("with element with child element with attribute and value", async function () { const xml: any = await parseXML(`yum`); assert.deepStrictEqual(xml, { - "apples": { - "$": { - "tasty": "true" + apples: { + $: { + tasty: "true", }, - "_": "yum" - } + _: "yum", + }, }); }); }); diff --git a/tslint.json b/tslint.json index aee3fc9..d7a1471 100644 --- a/tslint.json +++ b/tslint.json @@ -6,7 +6,13 @@ "class-name": true, "comment-format": [true, "check-space"], "indent": [true, "spaces"], - "ter-indent": [true, 2], + "ter-indent": [ + true, + 2, + { + "SwitchCase": 1 + } + ], "linebreak-style": [true, "LF"], "one-line": [true, "check-open-brace", diff --git a/webpack.testconfig.ts b/webpack.testconfig.ts index 49f3111..a07d6d5 100644 --- a/webpack.testconfig.ts +++ b/webpack.testconfig.ts @@ -3,7 +3,7 @@ import * as glob from "glob"; import * as path from "path"; const config: webpack.Configuration = { - entry: glob.sync(path.join(__dirname, "test/**/*[^node\.].ts")), + entry: glob.sync(path.join(__dirname, "test/**/*[^node.].ts")), mode: "development", devtool: "source-map", stats: { @@ -20,19 +20,37 @@ const config: webpack.Configuration = { errors: true, errorDetails: false, warnings: false, - publicPath: false + publicPath: false, }, output: { filename: "msRest.browser.test.js", - path: path.resolve(__dirname, "test") + path: path.resolve(__dirname, "test"), }, plugins: [ - new webpack.NormalModuleReplacementPlugin(/(\.).+util\/base64/, path.resolve(__dirname, "./lib/util/base64.browser.ts")), - new webpack.NormalModuleReplacementPlugin(/(\.).+util\/xml/, path.resolve(__dirname, "./lib/util/xml.browser.ts")), - new webpack.NormalModuleReplacementPlugin(/(\.).+defaultHttpClient/, path.resolve(__dirname, "./lib/defaultHttpClient.browser.ts")), - new webpack.NormalModuleReplacementPlugin(/(\.).+msRestUserAgentPolicy/, path.resolve(__dirname, "./lib/policies/msRestUserAgentPolicy.browser.ts")), - new webpack.NormalModuleReplacementPlugin(/(\.).+agentPolicy/, path.resolve(__dirname, "./lib/policies/agentPolicy.browser.ts")), - new webpack.NormalModuleReplacementPlugin(/(\.).+proxyPolicy/, path.resolve(__dirname, "./lib/policies/proxyPolicy.browser.ts")) + new webpack.NormalModuleReplacementPlugin( + /(\.).+util\/base64/, + path.resolve(__dirname, "./lib/util/base64.browser.ts") + ), + new webpack.NormalModuleReplacementPlugin( + /(\.).+util\/xml/, + path.resolve(__dirname, "./lib/util/xml.browser.ts") + ), + new webpack.NormalModuleReplacementPlugin( + /(\.).+defaultHttpClient/, + path.resolve(__dirname, "./lib/defaultHttpClient.browser.ts") + ), + new webpack.NormalModuleReplacementPlugin( + /(\.).+msRestUserAgentPolicy/, + path.resolve(__dirname, "./lib/policies/msRestUserAgentPolicy.browser.ts") + ), + new webpack.NormalModuleReplacementPlugin( + /(\.).+agentPolicy/, + path.resolve(__dirname, "./lib/policies/agentPolicy.browser.ts") + ), + new webpack.NormalModuleReplacementPlugin( + /(\.).+proxyPolicy/, + path.resolve(__dirname, "./lib/policies/proxyPolicy.browser.ts") + ), ], module: { rules: [ @@ -40,12 +58,12 @@ const config: webpack.Configuration = { test: /\.tsx?$/, loader: "ts-loader", exclude: /(node_modules)/, - options: { configFile: path.join(__dirname, "./tsconfig.es.json") } - } - ] + options: { configFile: path.join(__dirname, "./tsconfig.es.json") }, + }, + ], }, resolve: { - extensions: [".tsx", ".ts", ".js"] + extensions: [".tsx", ".ts", ".js"], }, node: { dns: false, @@ -57,7 +75,7 @@ const config: webpack.Configuration = { tty: false, tunnel: "empty", v8: false, - } + }, }; export = config;