import { PartitionKey, PartitionKeyDefinition } from "@azure/cosmos"; import * as DataModels from "../Contracts/DataModels"; import * as ViewModels from "../Contracts/ViewModels"; export function buildDocumentsQuery( filter: string, partitionKeyProperties: string[], partitionKey: DataModels.PartitionKey, ): string { let query = partitionKeyProperties && partitionKeyProperties.length > 0 ? `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; } 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); }; /* eslint-disable @typescript-eslint/no-explicit-any */ // export const extractPartitionKeyValues = ( // documentContent: any, // partitionKeyDefinition: PartitionKeyDefinition, // ): PartitionKey[] => { // if (!partitionKeyDefinition.paths || partitionKeyDefinition.paths.length === 0) { // return undefined; // } // const partitionKeyValues: PartitionKey[] = []; // partitionKeyDefinition.paths.forEach((partitionKeyPath: string) => { // const partitionKeyPathWithoutSlash: string = partitionKeyPath.substring(1); // // if (documentContent[partitionKeyPathWithoutSlash]) { // // partitionKeyValues.push(documentContent[partitionKeyPathWithoutSlash]); // // } // const partitionKeyPathParts: string[] = partitionKeyPathWithoutSlash.split("/"); // let partitionKeyValue: any = documentContent; // for(let partitionKeyPathPartIndex in partitionKeyPathParts) { // const partitionKeyPathPart: string = partitionKeyPathParts[partitionKeyPathPartIndex]; // if (!(partitionKeyPathPart in documentContent)) { // partitionKeyValue = {}; // break; // } // partitionKeyValue = partitionKeyValue[partitionKeyPathPart]; // } // partitionKeyValues.push(partitionKeyValue); // }); // return partitionKeyValues; // }; /* eslint-disable @typescript-eslint/no-explicit-any */ export const extractPartitionKeyValues = (document: any, partitionKeyDefinition: PartitionKeyDefinition): PartitionKey[] => { if (partitionKeyDefinition && partitionKeyDefinition.paths && partitionKeyDefinition.paths.length > 0) { var partitionKey: any = []; partitionKeyDefinition.paths.forEach(function (path) { path = path.substring(1); const pathParts: string[] = path.split("/"); var obj = document; for (var i = 0; i < pathParts.length; ++i) { if (!((typeof obj === "object") && (pathParts[i] in obj))) { obj = {}; break; } obj = obj[pathParts[i]]; } partitionKey.push(obj); }); return partitionKey; } return undefined; }