From 343e82c102231c21da1102ae57a5ff4b64ae073a Mon Sep 17 00:00:00 2001 From: Hardikkumar Nai <80053762+hardiknai-techm@users.noreply.github.com> Date: Tue, 30 Mar 2021 07:56:41 +0530 Subject: [PATCH] Fix lint query utils (#487) * Fix Lint errors in QueryUtils * Format * Simplify diff Co-authored-by: Your Name Co-authored-by: Steve Faulkner Co-authored-by: Steve Faulkner <471400+southpolesteve@users.noreply.github.com> Co-authored-by: Jordi Bunster --- .eslintignore | 1 - src/Common/QueriesClient.ts | 2 +- src/Explorer/Tabs/DocumentsTab.ts | 2 +- src/Explorer/Tabs/QueryTab.ts | 2 +- src/Utils/QueryUtils.test.ts | 2 +- src/Utils/QueryUtils.ts | 218 +++++++++++++++--------------- 6 files changed, 111 insertions(+), 116 deletions(-) diff --git a/.eslintignore b/.eslintignore index 889d8e8d8..e32b753fd 100644 --- a/.eslintignore +++ b/.eslintignore @@ -257,7 +257,6 @@ src/TokenProviders/PortalTokenProvider.ts src/TokenProviders/TokenProviderFactory.ts src/Utils/PricingUtils.test.ts src/Utils/QueryUtils.test.ts -src/Utils/QueryUtils.ts src/applyExplorerBindings.ts src/global.d.ts src/setupTests.ts diff --git a/src/Common/QueriesClient.ts b/src/Common/QueriesClient.ts index 3ecac7051..b7146fdbf 100644 --- a/src/Common/QueriesClient.ts +++ b/src/Common/QueriesClient.ts @@ -6,7 +6,7 @@ import Explorer from "../Explorer/Explorer"; import DocumentsTab from "../Explorer/Tabs/DocumentsTab"; import DocumentId from "../Explorer/Tree/DocumentId"; import * as NotificationConsoleUtils from "../Utils/NotificationConsoleUtils"; -import { QueryUtils } from "../Utils/QueryUtils"; +import * as QueryUtils from "../Utils/QueryUtils"; import { BackendDefaults, HttpStatusCodes, SavedQueries } from "./Constants"; import { userContext } from "../UserContext"; import { queryDocumentsPage } from "./dataAccess/queryDocumentsPage"; diff --git a/src/Explorer/Tabs/DocumentsTab.ts b/src/Explorer/Tabs/DocumentsTab.ts index f678db1b6..b27028d3b 100644 --- a/src/Explorer/Tabs/DocumentsTab.ts +++ b/src/Explorer/Tabs/DocumentsTab.ts @@ -11,7 +11,7 @@ import editable from "../../Common/EditableUtility"; import * as HeadersUtility from "../../Common/HeadersUtility"; import TabsBase from "./TabsBase"; import { DocumentsGridMetrics } from "../../Common/Constants"; -import { QueryUtils } from "../../Utils/QueryUtils"; +import * as QueryUtils from "../../Utils/QueryUtils"; import { Splitter, SplitterBounds, SplitterDirection } from "../../Common/Splitter"; import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor"; import NewDocumentIcon from "../../../images/NewDocument.svg"; diff --git a/src/Explorer/Tabs/QueryTab.ts b/src/Explorer/Tabs/QueryTab.ts index 089eaf959..b91043440 100644 --- a/src/Explorer/Tabs/QueryTab.ts +++ b/src/Explorer/Tabs/QueryTab.ts @@ -9,7 +9,7 @@ import * as HeadersUtility from "../../Common/HeadersUtility"; import { Splitter, SplitterBounds, SplitterDirection } from "../../Common/Splitter"; import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor"; import ExecuteQueryIcon from "../../../images/ExecuteQuery.svg"; -import { QueryUtils } from "../../Utils/QueryUtils"; +import * as QueryUtils from "../../Utils/QueryUtils"; import SaveQueryIcon from "../../../images/save-cosmos.svg"; import { MinimalQueryIterator } from "../../Common/IteratorUtilities"; diff --git a/src/Utils/QueryUtils.test.ts b/src/Utils/QueryUtils.test.ts index d05f57d2e..76e525a06 100644 --- a/src/Utils/QueryUtils.test.ts +++ b/src/Utils/QueryUtils.test.ts @@ -2,7 +2,7 @@ import * as DataModels from "../Contracts/DataModels"; import * as Q from "q"; import * as sinon from "sinon"; import * as ViewModels from "../Contracts/ViewModels"; -import { QueryUtils } from "./QueryUtils"; +import * as QueryUtils from "./QueryUtils"; describe("Query Utils", () => { function generatePartitionKeyForPath(path: string): DataModels.PartitionKey { diff --git a/src/Utils/QueryUtils.ts b/src/Utils/QueryUtils.ts index 2b3aafc90..b652df70f 100644 --- a/src/Utils/QueryUtils.ts +++ b/src/Utils/QueryUtils.ts @@ -1,118 +1,114 @@ -import Q from "q"; import * as DataModels from "../Contracts/DataModels"; import * as ViewModels from "../Contracts/ViewModels"; -export class QueryUtils { - public static buildDocumentsQuery( - filter: string, - partitionKeyProperty: string, - partitionKey: DataModels.PartitionKey - ): string { - let query: string = partitionKeyProperty - ? `select c.id, c._self, c._rid, c._ts, ${QueryUtils.buildDocumentsQueryPartitionProjections( - "c", - partitionKey - )} as _partitionKeyValue from c` - : `select c.id, c._self, c._rid, c._ts from c`; +export function buildDocumentsQuery( + filter: string, + partitionKeyProperty: string, + partitionKey: DataModels.PartitionKey +): string { + let query = partitionKeyProperty + ? `select c.id, c._self, c._rid, c._ts, ${buildDocumentsQueryPartitionProjections( + "c", + partitionKey + )} as _partitionKeyValue from c` + : `select c.id, c._self, c._rid, c._ts from c`; - if (filter) { - query += " " + filter; - } - - return query; + if (filter) { + query += " " + filter; } - public static buildDocumentsQueryPartitionProjections( - collectionAlias: string, - partitionKey: DataModels.PartitionKey - ): string { - if (!partitionKey) { - return ""; - } - - // e.g., path /order/id will be projected as c["order"]["id"], - // to escape any property names that match a keyword - let projections = []; - for (let index in partitionKey.paths) { - // TODO: Handle "/" in partition key definitions - const projectedProperties: string[] = partitionKey.paths[index].split("/").slice(1); - let projectedProperty: string = ""; - - projectedProperties.forEach((property: string) => { - const projection = property.trim(); - if (projection.length > 0 && projection.charAt(0) != "'" && projection.charAt(0) != '"') { - projectedProperty = projectedProperty + `["${projection}"]`; - } else if (projection.length > 0 && projection.charAt(0) == "'") { - // trim single quotes and escape double quotes - const projectionSlice = projection.slice(1, projection.length - 1); - projectedProperty = - projectedProperty + `["${projectionSlice.replace(/\\"/g, '"').replace(/"/g, '\\\\\\"')}"]`; - } else { - projectedProperty = projectedProperty + `[${projection}]`; - } - }); - - projections.push(`${collectionAlias}${projectedProperty}`); - } - - return projections.join(","); - } - - public static async queryPagesUntilContentPresent( - firstItemIndex: number, - queryItems: (itemIndex: number) => Promise - ): Promise { - let roundTrips: number = 0; - let netRequestCharge: number = 0; - const doRequest = async (itemIndex: number): Promise => { - const results: ViewModels.QueryResults = await queryItems(itemIndex); - roundTrips = roundTrips + 1; - results.roundTrips = roundTrips; - results.requestCharge = Number(results.requestCharge) + netRequestCharge; - netRequestCharge = Number(results.requestCharge); - const resultsMetadata: ViewModels.QueryResultsMetadata = { - hasMoreResults: results.hasMoreResults, - itemCount: results.itemCount, - firstItemIndex: results.firstItemIndex, - lastItemIndex: results.lastItemIndex, - }; - if (resultsMetadata.itemCount === 0 && resultsMetadata.hasMoreResults) { - return await doRequest(resultsMetadata.lastItemIndex); - } - return results; - }; - - return await doRequest(firstItemIndex); - } - - public static async queryAllPages( - queryItems: (itemIndex: number) => Promise - ): Promise { - const queryResults: ViewModels.QueryResults = { - documents: [], - activityId: undefined, - hasMoreResults: false, - itemCount: 0, - firstItemIndex: 0, - lastItemIndex: 0, - requestCharge: 0, - roundTrips: 0, - }; - const doRequest = async (itemIndex: number): Promise => { - const results: ViewModels.QueryResults = await queryItems(itemIndex); - const { requestCharge, hasMoreResults, itemCount, lastItemIndex, documents } = results; - queryResults.roundTrips = queryResults.roundTrips + 1; - queryResults.requestCharge = Number(queryResults.requestCharge) + Number(requestCharge); - queryResults.hasMoreResults = hasMoreResults; - queryResults.itemCount = queryResults.itemCount + itemCount; - queryResults.lastItemIndex = lastItemIndex; - queryResults.documents = queryResults.documents.concat(documents); - if (queryResults.hasMoreResults) { - return doRequest(queryResults.lastItemIndex + 1); - } - return queryResults; - }; - - return doRequest(0); - } + return query; } + +export function buildDocumentsQueryPartitionProjections( + collectionAlias: string, + partitionKey?: DataModels.PartitionKey +): string { + if (!partitionKey) { + return ""; + } + + // e.g., path /order/id will be projected as c["order"]["id"], + // to escape any property names that match a keyword + const projections = []; + for (const index in partitionKey.paths) { + // TODO: Handle "/" in partition key definitions + const projectedProperties: string[] = partitionKey.paths[index].split("/").slice(1); + let projectedProperty = ""; + + projectedProperties.forEach((property: string) => { + const projection = property.trim(); + if (projection.length > 0 && projection.charAt(0) !== "'" && projection.charAt(0) !== '"') { + projectedProperty += `["${projection}"]`; + } else if (projection.length > 0 && projection.charAt(0) === "'") { + // trim single quotes and escape double quotes + const projectionSlice = projection.slice(1, projection.length - 1); + projectedProperty += `["${projectionSlice.replace(/\\"/g, '"').replace(/"/g, '\\\\\\"')}"]`; + } else { + projectedProperty += `[${projection}]`; + } + }); + + projections.push(`${collectionAlias}${projectedProperty}`); + } + + return projections.join(","); +} + +export const queryPagesUntilContentPresent = async ( + firstItemIndex: number, + queryItems: (itemIndex: number) => Promise +): Promise => { + let roundTrips = 0; + let netRequestCharge = 0; + const doRequest = async (itemIndex: number): Promise => { + const results = await queryItems(itemIndex); + roundTrips = roundTrips + 1; + results.roundTrips = roundTrips; + results.requestCharge = Number(results.requestCharge) + netRequestCharge; + netRequestCharge = Number(results.requestCharge); + const resultsMetadata = { + hasMoreResults: results.hasMoreResults, + itemCount: results.itemCount, + firstItemIndex: results.firstItemIndex, + lastItemIndex: results.lastItemIndex, + }; + if (resultsMetadata.itemCount === 0 && resultsMetadata.hasMoreResults) { + return await doRequest(resultsMetadata.lastItemIndex); + } + return results; + }; + + return await doRequest(firstItemIndex); +}; + +export const queryAllPages = async ( + queryItems: (itemIndex: number) => Promise +): Promise => { + const queryResults: ViewModels.QueryResults = { + documents: [], + activityId: undefined, + hasMoreResults: false, + itemCount: 0, + firstItemIndex: 0, + lastItemIndex: 0, + requestCharge: 0, + roundTrips: 0, + }; + const doRequest = async (itemIndex: number): Promise => { + const results = await queryItems(itemIndex); + const { requestCharge, hasMoreResults, itemCount, lastItemIndex, documents } = results; + queryResults.roundTrips = queryResults.roundTrips + 1; + queryResults.requestCharge = Number(queryResults.requestCharge) + Number(requestCharge); + queryResults.hasMoreResults = hasMoreResults; + queryResults.itemCount = queryResults.itemCount + itemCount; + queryResults.lastItemIndex = lastItemIndex; + queryResults.documents = queryResults.documents.concat(documents); + if (queryResults.hasMoreResults) { + return doRequest(queryResults.lastItemIndex + 1); + } + return queryResults; + }; + + return doRequest(0); +};