UNPKG

@azure/cosmos

Version:

Microsoft Azure Cosmos DB Service Node.js SDK for NOSQL API

1,114 lines (1,100 loc) • 660 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var crypto = require('crypto'); var logger$5 = require('@azure/logger'); var coreUtil = require('@azure/core-util'); var tslib = require('tslib'); var PriorityQueue = require('priorityqueuejs'); var semaphore = require('semaphore'); var stableStringify = require('fast-json-stable-stringify'); var coreRestPipeline = require('@azure/core-rest-pipeline'); var process$1 = require('node:process'); var JSBI = require('jsbi'); var abortController = require('@azure/abort-controller'); var keyvaultKeys = require('@azure/keyvault-keys'); // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. const DEFAULT_PARTITION_KEY_PATH = "/_partitionKey"; // eslint-disable-line @typescript-eslint/prefer-as-const // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. /** * @hidden */ const Constants = { HttpHeaders: { Authorization: "authorization", ETag: "etag", MethodOverride: "X-HTTP-Method", Slug: "Slug", ContentType: "Content-Type", LastModified: "Last-Modified", ContentEncoding: "Content-Encoding", CharacterSet: "CharacterSet", UserAgent: "User-Agent", CustomUserAgent: "x-ms-useragent", IfModifiedSince: "If-Modified-Since", IfMatch: "If-Match", IfNoneMatch: "If-None-Match", ContentLength: "Content-Length", AcceptEncoding: "Accept-Encoding", KeepAlive: "Keep-Alive", CacheControl: "Cache-Control", TransferEncoding: "Transfer-Encoding", ContentLanguage: "Content-Language", ContentLocation: "Content-Location", ContentMd5: "Content-Md5", ContentRange: "Content-Range", Accept: "Accept", AcceptCharset: "Accept-Charset", AcceptLanguage: "Accept-Language", IfRange: "If-Range", IfUnmodifiedSince: "If-Unmodified-Since", MaxForwards: "Max-Forwards", ProxyAuthorization: "Proxy-Authorization", AcceptRanges: "Accept-Ranges", ProxyAuthenticate: "Proxy-Authenticate", RetryAfter: "Retry-After", SetCookie: "Set-Cookie", WwwAuthenticate: "Www-Authenticate", Origin: "Origin", Host: "Host", AccessControlAllowOrigin: "Access-Control-Allow-Origin", AccessControlAllowHeaders: "Access-Control-Allow-Headers", KeyValueEncodingFormat: "application/x-www-form-urlencoded", WrapAssertionFormat: "wrap_assertion_format", WrapAssertion: "wrap_assertion", WrapScope: "wrap_scope", SimpleToken: "SWT", HttpDate: "date", Prefer: "Prefer", Location: "Location", Referer: "referer", A_IM: "A-IM", // Query Query: "x-ms-documentdb-query", IsQuery: "x-ms-documentdb-isquery", IsQueryPlan: "x-ms-cosmos-is-query-plan-request", SupportedQueryFeatures: "x-ms-cosmos-supported-query-features", QueryVersion: "x-ms-cosmos-query-version", // Our custom Azure Cosmos DB headers Continuation: "x-ms-continuation", ContinuationToken: "x-ms-continuation-token", PageSize: "x-ms-max-item-count", ItemCount: "x-ms-item-count", ChangeFeedWireFormatVersion: "x-ms-cosmos-changefeed-wire-format-version", // Request sender generated. Simply echoed by backend. ActivityId: "x-ms-activity-id", CorrelatedActivityId: "x-ms-cosmos-correlated-activityid", PreTriggerInclude: "x-ms-documentdb-pre-trigger-include", PreTriggerExclude: "x-ms-documentdb-pre-trigger-exclude", PostTriggerInclude: "x-ms-documentdb-post-trigger-include", PostTriggerExclude: "x-ms-documentdb-post-trigger-exclude", IndexingDirective: "x-ms-indexing-directive", SessionToken: "x-ms-session-token", ConsistencyLevel: "x-ms-consistency-level", XDate: "x-ms-date", CollectionPartitionInfo: "x-ms-collection-partition-info", CollectionServiceInfo: "x-ms-collection-service-info", // Deprecated, use RetryAfterInMs instead. RetryAfterInMilliseconds: "x-ms-retry-after-ms", RetryAfterInMs: "x-ms-retry-after-ms", IsFeedUnfiltered: "x-ms-is-feed-unfiltered", ResourceTokenExpiry: "x-ms-documentdb-expiry-seconds", EnableScanInQuery: "x-ms-documentdb-query-enable-scan", EmitVerboseTracesInQuery: "x-ms-documentdb-query-emit-traces", EnableCrossPartitionQuery: "x-ms-documentdb-query-enablecrosspartition", ParallelizeCrossPartitionQuery: "x-ms-documentdb-query-parallelizecrosspartitionquery", ResponseContinuationTokenLimitInKB: "x-ms-documentdb-responsecontinuationtokenlimitinkb", SDKSupportedCapabilities: "x-ms-cosmos-sdk-supportedcapabilities", // QueryMetrics // Request header to tell backend to give you query metrics. PopulateQueryMetrics: "x-ms-documentdb-populatequerymetrics", // Response header that holds the serialized version of query metrics. QueryMetrics: "x-ms-documentdb-query-metrics", // IndexMetrics // Request header to tell backend to give you index metrics. PopulateIndexMetrics: "x-ms-cosmos-populateindexmetrics-V2", // Response header that holds the serialized version of index metrics. IndexUtilization: "x-ms-cosmos-index-utilization", // Version headers and values Version: "x-ms-version", // Owner name OwnerFullName: "x-ms-alt-content-path", // Owner ID used for name based request in session token. OwnerId: "x-ms-content-path", // Partition Key PartitionKey: "x-ms-documentdb-partitionkey", PartitionKeyRangeID: "x-ms-documentdb-partitionkeyrangeid", // Epk Range headers StartEpk: "x-ms-start-epk", EndEpk: "x-ms-end-epk", // Read Feed Type ReadFeedKeyType: "x-ms-read-key-type", // Quota Info MaxEntityCount: "x-ms-root-entity-max-count", CurrentEntityCount: "x-ms-root-entity-current-count", CollectionQuotaInMb: "x-ms-collection-quota-mb", CollectionCurrentUsageInMb: "x-ms-collection-usage-mb", MaxMediaStorageUsageInMB: "x-ms-max-media-storage-usage-mb", CurrentMediaStorageUsageInMB: "x-ms-media-storage-usage-mb", RequestCharge: "x-ms-request-charge", PopulateQuotaInfo: "x-ms-documentdb-populatequotainfo", MaxResourceQuota: "x-ms-resource-quota", // Offer header OfferType: "x-ms-offer-type", OfferThroughput: "x-ms-offer-throughput", AutoscaleSettings: "x-ms-cosmos-offer-autopilot-settings", // Custom RUs/minute headers DisableRUPerMinuteUsage: "x-ms-documentdb-disable-ru-per-minute-usage", IsRUPerMinuteUsed: "x-ms-documentdb-is-ru-per-minute-used", OfferIsRUPerMinuteThroughputEnabled: "x-ms-offer-is-ru-per-minute-throughput-enabled", // Index progress headers IndexTransformationProgress: "x-ms-documentdb-collection-index-transformation-progress", LazyIndexingProgress: "x-ms-documentdb-collection-lazy-indexing-progress", // Upsert header IsUpsert: "x-ms-documentdb-is-upsert", // Sub status of the error SubStatus: "x-ms-substatus", // StoredProcedure related headers EnableScriptLogging: "x-ms-documentdb-script-enable-logging", ScriptLogResults: "x-ms-documentdb-script-log-results", // Multi-Region Write ALLOW_MULTIPLE_WRITES: "x-ms-cosmos-allow-tentative-writes", // Bulk/Batch header IsBatchRequest: "x-ms-cosmos-is-batch-request", IsBatchAtomic: "x-ms-cosmos-batch-atomic", BatchContinueOnError: "x-ms-cosmos-batch-continue-on-error", // Dedicated Gateway Headers DedicatedGatewayPerRequestCacheStaleness: "x-ms-dedicatedgateway-max-age", DedicatedGatewayPerRequestBypassCache: "x-ms-dedicatedgateway-bypass-cache", // Cache Refresh header ForceRefresh: "x-ms-force-refresh", // Throughput related headers PriorityLevel: "x-ms-cosmos-priority-level", ThroughputBucket: "x-ms-cosmos-throughput-bucket", // Encryption Headers IsClientEncryptedHeader: "x-ms-cosmos-is-client-encrypted", IntendedCollectionHeader: "x-ms-cosmos-intended-collection-rid", DatabaseRidHeader: "x-ms-cosmos-database-rid", AllowCachedReadsHeader: "x-ms-cosmos-allow-cachedreads", }, // ThrottledRequests Retry policy default values ThrottledRequestMaxRetryAttemptCount: 9, ThrottledRequestMaxWaitTimeInSeconds: 30, ThrottledRequestFixedRetryIntervalInMs: 0, // GlobalDB related constants WritableLocations: "writableLocations", ReadableLocations: "readableLocations", LocationUnavailableExpirationTimeInMs: 5 * 60 * 1000, // 5 minutes // ServiceDocument Resource ENABLE_MULTIPLE_WRITABLE_LOCATIONS: "enableMultipleWriteLocations", // Background refresh time DefaultUnavailableLocationExpirationTimeMS: 5 * 60 * 1000, // Client generated retry count response header ThrottleRetryCount: "x-ms-throttle-retry-count", ThrottleRetryWaitTimeInMs: "x-ms-throttle-retry-wait-time-ms", // Platform CurrentVersion: "2020-07-15", AzureNamespace: "Azure.Cosmos", AzurePackageName: "@azure/cosmos", SDKName: "azure-cosmos-js", SDKVersion: "4.3.0", // Diagnostics CosmosDbDiagnosticLevelEnvVarName: "AZURE_COSMOSDB_DIAGNOSTICS_LEVEL", // Bulk Operations DefaultMaxBulkRequestBodySizeInBytes: 220201, // Encryption Encryption: { DiagnosticsDecryptOperation: "Decrypt", DiagnosticsDuration: "Duration in milliseconds", DiagnosticsEncryptionDiagnostics: "EncryptionDiagnostics", DiagnosticsEncryptOperation: "Encrypt", DiagnosticsPropertiesEncryptedCount: "Properties Encrypted Count", DiagnosticsPropertiesDecryptedCount: "Properties Decrypted Count", DiagnosticsStartTime: "Start time", }, Quota: { CollectionSize: "collectionSize", }, Path: { Root: "/", DatabasesPathSegment: "dbs", CollectionsPathSegment: "colls", UsersPathSegment: "users", DocumentsPathSegment: "docs", PermissionsPathSegment: "permissions", StoredProceduresPathSegment: "sprocs", TriggersPathSegment: "triggers", UserDefinedFunctionsPathSegment: "udfs", ConflictsPathSegment: "conflicts", AttachmentsPathSegment: "attachments", PartitionKeyRangesPathSegment: "pkranges", SchemasPathSegment: "schemas", OffersPathSegment: "offers", TopologyPathSegment: "topology", DatabaseAccountPathSegment: "databaseaccount", }, PartitionKeyRange: { // Partition Key Range Constants MinInclusive: "minInclusive", MaxExclusive: "maxExclusive", Id: "id", }, QueryRangeConstants: { // Partition Key Range Constants MinInclusive: "minInclusive", MaxExclusive: "maxExclusive", min: "min", }, /** * @deprecated Use EffectivePartitionKeyConstants instead */ EffectiveParitionKeyConstants: { MinimumInclusiveEffectivePartitionKey: "", MaximumExclusiveEffectivePartitionKey: "FF", }, EffectivePartitionKeyConstants: { MinimumInclusiveEffectivePartitionKey: "", MaximumExclusiveEffectivePartitionKey: "FF", }, // Changefeed AllVersionsAndDeletesMode formatting version AllVersionsAndDeletesChangeFeedWireFormatVersion: "2021-09-15", ChangeFeedIfNoneMatchStartFromNowHeader: "*", // Default TTL for encryption caches is 2 hrs (7200 sec) DefaultEncryptionCacheTimeToLiveInSeconds: 7200, // Timeout to clear encryption related cache EncryptionCacheRefreshIntervalInMs: 60000, // 1 minute }; /** * @hidden */ exports.ResourceType = void 0; (function (ResourceType) { ResourceType["none"] = ""; ResourceType["database"] = "dbs"; ResourceType["offer"] = "offers"; ResourceType["user"] = "users"; ResourceType["permission"] = "permissions"; ResourceType["container"] = "colls"; ResourceType["conflicts"] = "conflicts"; ResourceType["sproc"] = "sprocs"; ResourceType["udf"] = "udfs"; ResourceType["trigger"] = "triggers"; ResourceType["item"] = "docs"; ResourceType["pkranges"] = "pkranges"; ResourceType["partitionkey"] = "partitionKey"; /** resource representing client encryption keys to encrypt/decrypt data */ ResourceType["clientencryptionkey"] = "clientencryptionkeys"; })(exports.ResourceType || (exports.ResourceType = {})); /** * @hidden */ exports.HTTPMethod = void 0; (function (HTTPMethod) { HTTPMethod["get"] = "GET"; HTTPMethod["patch"] = "PATCH"; HTTPMethod["post"] = "POST"; HTTPMethod["put"] = "PUT"; HTTPMethod["delete"] = "DELETE"; })(exports.HTTPMethod || (exports.HTTPMethod = {})); /** * @hidden */ exports.OperationType = void 0; (function (OperationType) { OperationType["Create"] = "create"; OperationType["Replace"] = "replace"; OperationType["Upsert"] = "upsert"; OperationType["Delete"] = "delete"; OperationType["Read"] = "read"; OperationType["Query"] = "query"; OperationType["Execute"] = "execute"; OperationType["Batch"] = "batch"; OperationType["Patch"] = "patch"; })(exports.OperationType || (exports.OperationType = {})); /** * @hidden */ var CosmosKeyType; (function (CosmosKeyType) { CosmosKeyType["PrimaryMaster"] = "PRIMARY_MASTER"; CosmosKeyType["SecondaryMaster"] = "SECONDARY_MASTER"; CosmosKeyType["PrimaryReadOnly"] = "PRIMARY_READONLY"; CosmosKeyType["SecondaryReadOnly"] = "SECONDARY_READONLY"; })(CosmosKeyType || (CosmosKeyType = {})); /** * @hidden */ var CosmosContainerChildResourceKind; (function (CosmosContainerChildResourceKind) { CosmosContainerChildResourceKind["Item"] = "ITEM"; CosmosContainerChildResourceKind["StoredProcedure"] = "STORED_PROCEDURE"; CosmosContainerChildResourceKind["UserDefinedFunction"] = "USER_DEFINED_FUNCTION"; CosmosContainerChildResourceKind["Trigger"] = "TRIGGER"; })(CosmosContainerChildResourceKind || (CosmosContainerChildResourceKind = {})); /** * @hidden */ var PermissionScopeValues; (function (PermissionScopeValues) { /** * Values which set permission Scope applicable to control plane related operations. */ PermissionScopeValues[PermissionScopeValues["ScopeAccountReadValue"] = 1] = "ScopeAccountReadValue"; PermissionScopeValues[PermissionScopeValues["ScopeAccountListDatabasesValue"] = 2] = "ScopeAccountListDatabasesValue"; PermissionScopeValues[PermissionScopeValues["ScopeDatabaseReadValue"] = 4] = "ScopeDatabaseReadValue"; PermissionScopeValues[PermissionScopeValues["ScopeDatabaseReadOfferValue"] = 8] = "ScopeDatabaseReadOfferValue"; PermissionScopeValues[PermissionScopeValues["ScopeDatabaseListContainerValue"] = 16] = "ScopeDatabaseListContainerValue"; PermissionScopeValues[PermissionScopeValues["ScopeContainerReadValue"] = 32] = "ScopeContainerReadValue"; PermissionScopeValues[PermissionScopeValues["ScopeContainerReadOfferValue"] = 64] = "ScopeContainerReadOfferValue"; PermissionScopeValues[PermissionScopeValues["ScopeAccountCreateDatabasesValue"] = 1] = "ScopeAccountCreateDatabasesValue"; PermissionScopeValues[PermissionScopeValues["ScopeAccountDeleteDatabasesValue"] = 2] = "ScopeAccountDeleteDatabasesValue"; PermissionScopeValues[PermissionScopeValues["ScopeDatabaseDeleteValue"] = 4] = "ScopeDatabaseDeleteValue"; PermissionScopeValues[PermissionScopeValues["ScopeDatabaseReplaceOfferValue"] = 8] = "ScopeDatabaseReplaceOfferValue"; PermissionScopeValues[PermissionScopeValues["ScopeDatabaseCreateContainerValue"] = 16] = "ScopeDatabaseCreateContainerValue"; PermissionScopeValues[PermissionScopeValues["ScopeDatabaseDeleteContainerValue"] = 32] = "ScopeDatabaseDeleteContainerValue"; PermissionScopeValues[PermissionScopeValues["ScopeContainerReplaceValue"] = 64] = "ScopeContainerReplaceValue"; PermissionScopeValues[PermissionScopeValues["ScopeContainerDeleteValue"] = 128] = "ScopeContainerDeleteValue"; PermissionScopeValues[PermissionScopeValues["ScopeContainerReplaceOfferValue"] = 256] = "ScopeContainerReplaceOfferValue"; PermissionScopeValues[PermissionScopeValues["ScopeAccountReadAllAccessValue"] = 65535] = "ScopeAccountReadAllAccessValue"; PermissionScopeValues[PermissionScopeValues["ScopeDatabaseReadAllAccessValue"] = 124] = "ScopeDatabaseReadAllAccessValue"; PermissionScopeValues[PermissionScopeValues["ScopeContainersReadAllAccessValue"] = 96] = "ScopeContainersReadAllAccessValue"; PermissionScopeValues[PermissionScopeValues["ScopeAccountWriteAllAccessValue"] = 65535] = "ScopeAccountWriteAllAccessValue"; PermissionScopeValues[PermissionScopeValues["ScopeDatabaseWriteAllAccessValue"] = 508] = "ScopeDatabaseWriteAllAccessValue"; PermissionScopeValues[PermissionScopeValues["ScopeContainersWriteAllAccessValue"] = 448] = "ScopeContainersWriteAllAccessValue"; /** * Values which set permission Scope applicable to data plane related operations. */ PermissionScopeValues[PermissionScopeValues["ScopeContainerExecuteQueriesValue"] = 1] = "ScopeContainerExecuteQueriesValue"; PermissionScopeValues[PermissionScopeValues["ScopeContainerReadFeedsValue"] = 2] = "ScopeContainerReadFeedsValue"; PermissionScopeValues[PermissionScopeValues["ScopeContainerReadStoredProceduresValue"] = 4] = "ScopeContainerReadStoredProceduresValue"; PermissionScopeValues[PermissionScopeValues["ScopeContainerReadUserDefinedFunctionsValue"] = 8] = "ScopeContainerReadUserDefinedFunctionsValue"; PermissionScopeValues[PermissionScopeValues["ScopeContainerReadTriggersValue"] = 16] = "ScopeContainerReadTriggersValue"; PermissionScopeValues[PermissionScopeValues["ScopeContainerReadConflictsValue"] = 32] = "ScopeContainerReadConflictsValue"; PermissionScopeValues[PermissionScopeValues["ScopeItemReadValue"] = 64] = "ScopeItemReadValue"; PermissionScopeValues[PermissionScopeValues["ScopeStoredProcedureReadValue"] = 128] = "ScopeStoredProcedureReadValue"; PermissionScopeValues[PermissionScopeValues["ScopeUserDefinedFunctionReadValue"] = 256] = "ScopeUserDefinedFunctionReadValue"; PermissionScopeValues[PermissionScopeValues["ScopeTriggerReadValue"] = 512] = "ScopeTriggerReadValue"; PermissionScopeValues[PermissionScopeValues["ScopeContainerCreateItemsValue"] = 1] = "ScopeContainerCreateItemsValue"; PermissionScopeValues[PermissionScopeValues["ScopeContainerReplaceItemsValue"] = 2] = "ScopeContainerReplaceItemsValue"; PermissionScopeValues[PermissionScopeValues["ScopeContainerUpsertItemsValue"] = 4] = "ScopeContainerUpsertItemsValue"; PermissionScopeValues[PermissionScopeValues["ScopeContainerDeleteItemsValue"] = 8] = "ScopeContainerDeleteItemsValue"; PermissionScopeValues[PermissionScopeValues["ScopeContainerCreateStoredProceduresValue"] = 16] = "ScopeContainerCreateStoredProceduresValue"; PermissionScopeValues[PermissionScopeValues["ScopeContainerReplaceStoredProceduresValue"] = 32] = "ScopeContainerReplaceStoredProceduresValue"; PermissionScopeValues[PermissionScopeValues["ScopeContainerDeleteStoredProceduresValue"] = 64] = "ScopeContainerDeleteStoredProceduresValue"; PermissionScopeValues[PermissionScopeValues["ScopeContainerExecuteStoredProceduresValue"] = 128] = "ScopeContainerExecuteStoredProceduresValue"; PermissionScopeValues[PermissionScopeValues["ScopeContainerCreateTriggersValue"] = 256] = "ScopeContainerCreateTriggersValue"; PermissionScopeValues[PermissionScopeValues["ScopeContainerReplaceTriggersValue"] = 512] = "ScopeContainerReplaceTriggersValue"; PermissionScopeValues[PermissionScopeValues["ScopeContainerDeleteTriggersValue"] = 1024] = "ScopeContainerDeleteTriggersValue"; PermissionScopeValues[PermissionScopeValues["ScopeContainerCreateUserDefinedFunctionsValue"] = 2048] = "ScopeContainerCreateUserDefinedFunctionsValue"; PermissionScopeValues[PermissionScopeValues["ScopeContainerReplaceUserDefinedFunctionsValue"] = 4096] = "ScopeContainerReplaceUserDefinedFunctionsValue"; PermissionScopeValues[PermissionScopeValues["ScopeContainerDeleteUserDefinedFunctionSValue"] = 8192] = "ScopeContainerDeleteUserDefinedFunctionSValue"; PermissionScopeValues[PermissionScopeValues["ScopeContainerDeleteCONFLICTSValue"] = 16384] = "ScopeContainerDeleteCONFLICTSValue"; PermissionScopeValues[PermissionScopeValues["ScopeItemReplaceValue"] = 65536] = "ScopeItemReplaceValue"; PermissionScopeValues[PermissionScopeValues["ScopeItemUpsertValue"] = 131072] = "ScopeItemUpsertValue"; PermissionScopeValues[PermissionScopeValues["ScopeItemDeleteValue"] = 262144] = "ScopeItemDeleteValue"; PermissionScopeValues[PermissionScopeValues["ScopeStoredProcedureReplaceValue"] = 1048576] = "ScopeStoredProcedureReplaceValue"; PermissionScopeValues[PermissionScopeValues["ScopeStoredProcedureDeleteValue"] = 2097152] = "ScopeStoredProcedureDeleteValue"; PermissionScopeValues[PermissionScopeValues["ScopeStoredProcedureExecuteValue"] = 4194304] = "ScopeStoredProcedureExecuteValue"; PermissionScopeValues[PermissionScopeValues["ScopeUserDefinedFunctionReplaceValue"] = 8388608] = "ScopeUserDefinedFunctionReplaceValue"; PermissionScopeValues[PermissionScopeValues["ScopeUserDefinedFunctionDeleteValue"] = 16777216] = "ScopeUserDefinedFunctionDeleteValue"; PermissionScopeValues[PermissionScopeValues["ScopeTriggerReplaceValue"] = 33554432] = "ScopeTriggerReplaceValue"; PermissionScopeValues[PermissionScopeValues["ScopeTriggerDeleteValue"] = 67108864] = "ScopeTriggerDeleteValue"; PermissionScopeValues[PermissionScopeValues["ScopeContainerReadAllAccessValue"] = 4294967295] = "ScopeContainerReadAllAccessValue"; PermissionScopeValues[PermissionScopeValues["ScopeItemReadAllAccessValue"] = 65] = "ScopeItemReadAllAccessValue"; PermissionScopeValues[PermissionScopeValues["ScopeContainerWriteAllAccessValue"] = 4294967295] = "ScopeContainerWriteAllAccessValue"; PermissionScopeValues[PermissionScopeValues["ScopeItemWriteAllAccessValue"] = 458767] = "ScopeItemWriteAllAccessValue"; PermissionScopeValues[PermissionScopeValues["NoneValue"] = 0] = "NoneValue"; })(PermissionScopeValues || (PermissionScopeValues = {})); /** * @hidden */ exports.SasTokenPermissionKind = void 0; (function (SasTokenPermissionKind) { SasTokenPermissionKind[SasTokenPermissionKind["ContainerCreateItems"] = 1] = "ContainerCreateItems"; SasTokenPermissionKind[SasTokenPermissionKind["ContainerReplaceItems"] = 2] = "ContainerReplaceItems"; SasTokenPermissionKind[SasTokenPermissionKind["ContainerUpsertItems"] = 4] = "ContainerUpsertItems"; SasTokenPermissionKind[SasTokenPermissionKind["ContainerDeleteItems"] = 128] = "ContainerDeleteItems"; SasTokenPermissionKind[SasTokenPermissionKind["ContainerExecuteQueries"] = 1] = "ContainerExecuteQueries"; SasTokenPermissionKind[SasTokenPermissionKind["ContainerReadFeeds"] = 2] = "ContainerReadFeeds"; SasTokenPermissionKind[SasTokenPermissionKind["ContainerCreateStoreProcedure"] = 16] = "ContainerCreateStoreProcedure"; SasTokenPermissionKind[SasTokenPermissionKind["ContainerReadStoreProcedure"] = 4] = "ContainerReadStoreProcedure"; SasTokenPermissionKind[SasTokenPermissionKind["ContainerReplaceStoreProcedure"] = 32] = "ContainerReplaceStoreProcedure"; SasTokenPermissionKind[SasTokenPermissionKind["ContainerDeleteStoreProcedure"] = 64] = "ContainerDeleteStoreProcedure"; SasTokenPermissionKind[SasTokenPermissionKind["ContainerCreateTriggers"] = 256] = "ContainerCreateTriggers"; SasTokenPermissionKind[SasTokenPermissionKind["ContainerReadTriggers"] = 16] = "ContainerReadTriggers"; SasTokenPermissionKind[SasTokenPermissionKind["ContainerReplaceTriggers"] = 512] = "ContainerReplaceTriggers"; SasTokenPermissionKind[SasTokenPermissionKind["ContainerDeleteTriggers"] = 1024] = "ContainerDeleteTriggers"; SasTokenPermissionKind[SasTokenPermissionKind["ContainerCreateUserDefinedFunctions"] = 2048] = "ContainerCreateUserDefinedFunctions"; SasTokenPermissionKind[SasTokenPermissionKind["ContainerReadUserDefinedFunctions"] = 8] = "ContainerReadUserDefinedFunctions"; SasTokenPermissionKind[SasTokenPermissionKind["ContainerReplaceUserDefinedFunctions"] = 4096] = "ContainerReplaceUserDefinedFunctions"; SasTokenPermissionKind[SasTokenPermissionKind["ContainerDeleteUserDefinedFunctions"] = 8192] = "ContainerDeleteUserDefinedFunctions"; SasTokenPermissionKind[SasTokenPermissionKind["ContainerExecuteStoredProcedure"] = 128] = "ContainerExecuteStoredProcedure"; SasTokenPermissionKind[SasTokenPermissionKind["ContainerReadConflicts"] = 32] = "ContainerReadConflicts"; SasTokenPermissionKind[SasTokenPermissionKind["ContainerDeleteConflicts"] = 16384] = "ContainerDeleteConflicts"; SasTokenPermissionKind[SasTokenPermissionKind["ContainerReadAny"] = 64] = "ContainerReadAny"; SasTokenPermissionKind[SasTokenPermissionKind["ContainerFullAccess"] = 4294967295] = "ContainerFullAccess"; SasTokenPermissionKind[SasTokenPermissionKind["ItemReadAny"] = 65536] = "ItemReadAny"; SasTokenPermissionKind[SasTokenPermissionKind["ItemFullAccess"] = 65] = "ItemFullAccess"; SasTokenPermissionKind[SasTokenPermissionKind["ItemRead"] = 64] = "ItemRead"; SasTokenPermissionKind[SasTokenPermissionKind["ItemReplace"] = 65536] = "ItemReplace"; SasTokenPermissionKind[SasTokenPermissionKind["ItemUpsert"] = 131072] = "ItemUpsert"; SasTokenPermissionKind[SasTokenPermissionKind["ItemDelete"] = 262144] = "ItemDelete"; SasTokenPermissionKind[SasTokenPermissionKind["StoreProcedureRead"] = 128] = "StoreProcedureRead"; SasTokenPermissionKind[SasTokenPermissionKind["StoreProcedureReplace"] = 1048576] = "StoreProcedureReplace"; SasTokenPermissionKind[SasTokenPermissionKind["StoreProcedureDelete"] = 2097152] = "StoreProcedureDelete"; SasTokenPermissionKind[SasTokenPermissionKind["StoreProcedureExecute"] = 4194304] = "StoreProcedureExecute"; SasTokenPermissionKind[SasTokenPermissionKind["UserDefinedFuntionRead"] = 256] = "UserDefinedFuntionRead"; SasTokenPermissionKind[SasTokenPermissionKind["UserDefinedFuntionReplace"] = 8388608] = "UserDefinedFuntionReplace"; SasTokenPermissionKind[SasTokenPermissionKind["UserDefinedFuntionDelete"] = 16777216] = "UserDefinedFuntionDelete"; SasTokenPermissionKind[SasTokenPermissionKind["TriggerRead"] = 512] = "TriggerRead"; SasTokenPermissionKind[SasTokenPermissionKind["TriggerReplace"] = 33554432] = "TriggerReplace"; SasTokenPermissionKind[SasTokenPermissionKind["TriggerDelete"] = 67108864] = "TriggerDelete"; })(exports.SasTokenPermissionKind || (exports.SasTokenPermissionKind = {})); var QueryFeature; (function (QueryFeature) { QueryFeature["NonValueAggregate"] = "NonValueAggregate"; QueryFeature["Aggregate"] = "Aggregate"; QueryFeature["Distinct"] = "Distinct"; QueryFeature["MultipleOrderBy"] = "MultipleOrderBy"; QueryFeature["OffsetAndLimit"] = "OffsetAndLimit"; QueryFeature["OrderBy"] = "OrderBy"; QueryFeature["Top"] = "Top"; QueryFeature["CompositeAggregate"] = "CompositeAggregate"; QueryFeature["GroupBy"] = "GroupBy"; QueryFeature["MultipleAggregates"] = "MultipleAggregates"; QueryFeature["NonStreamingOrderBy"] = "NonStreamingOrderBy"; QueryFeature["ListAndSetAggregate"] = "ListAndSetAggregate"; QueryFeature["CountIf"] = "CountIf"; QueryFeature["HybridSearch"] = "HybridSearch"; })(QueryFeature || (QueryFeature = {})); var SDKSupportedCapabilities; (function (SDKSupportedCapabilities) { SDKSupportedCapabilities[SDKSupportedCapabilities["PartitionMerge"] = 1] = "PartitionMerge"; })(SDKSupportedCapabilities || (SDKSupportedCapabilities = {})); // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. class BooleanSerializer { serialize(value) { const numValue = value ? 1 : 0; const buffer = Buffer.alloc(8); buffer.writeBigInt64LE(BigInt(numValue), 0); return buffer; } deserialize(bytes) { if (!bytes || bytes.length < 1) { throw new Error("Invalid byte array for deserialization"); } return !!bytes[0]; } } // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. class NumberSerializer { deserialize(bytes) { if (!bytes || bytes.length < 8) { throw new Error("Invalid byte array for deserialization"); } const num = Number(bytes.readBigInt64LE(0)); return num; } serialize(value) { const newValue = BigInt(value); const buffer = Buffer.alloc(8); buffer.writeBigInt64LE(newValue, 0); return buffer; } } // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. class FloatSerializer { deserialize(bytes) { if (!bytes || bytes.length < 8) { throw new Error("Invalid byte array for deserialization"); } const res = bytes.readDoubleLE(0); return res; } serialize(value) { if (!Number.isFinite(value)) { throw new Error("Value is out of range"); } const buffer = Buffer.alloc(8); buffer.writeDoubleLE(value, 0); return buffer; } } // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. class StringSerializer { deserialize(bytes) { return bytes.toString(StringSerializer.characterEncoding); } serialize(value) { return Buffer.from(value, StringSerializer.characterEncoding); } } StringSerializer.characterEncoding = "utf-8"; // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. /** * The type of encryption to be performed. */ exports.EncryptionType = void 0; (function (EncryptionType) { /** Deterministic type will always produce same encrypted value for same plaintext. */ EncryptionType["DETERMINISTIC"] = "Deterministic"; /** Randomized type will produce different encrypted value for same plaintext. */ EncryptionType["RANDOMIZED"] = "Randomized"; })(exports.EncryptionType || (exports.EncryptionType = {})); // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. var TypeMarker; (function (TypeMarker) { TypeMarker[TypeMarker["Null"] = 1] = "Null"; TypeMarker[TypeMarker["Boolean"] = 2] = "Boolean"; TypeMarker[TypeMarker["Double"] = 3] = "Double"; TypeMarker[TypeMarker["Long"] = 4] = "Long"; TypeMarker[TypeMarker["String"] = 5] = "String"; })(TypeMarker || (TypeMarker = {})); class ErrorResponse extends Error { } const trimLeftSlashes = new RegExp("^[/]+"); const trimRightSlashes = new RegExp("[/]+$"); const illegalResourceIdCharacters = new RegExp("[/\\\\?#]"); const illegalItemResourceIdCharacters = new RegExp("[/\\\\#]"); /** @hidden */ function jsonStringifyAndEscapeNonASCII(arg) { // TODO: better way for this? Not sure. // escapes non-ASCII characters as \uXXXX return JSON.stringify(arg).replace(/[\u007F-\uFFFF]/g, (m) => { return "\\u" + ("0000" + m.charCodeAt(0).toString(16)).slice(-4); }); } /** * @hidden */ function parseLink(resourcePath) { if (resourcePath.length === 0) { /* for DatabaseAccount case, both type and objectBody will be undefined. */ return { type: undefined, objectBody: undefined, }; } if (resourcePath[resourcePath.length - 1] !== "/") { resourcePath = resourcePath + "/"; } if (resourcePath[0] !== "/") { resourcePath = "/" + resourcePath; } /* The path will be in the form of /[resourceType]/[resourceId]/ .... /[resourceType]//[resourceType]/[resourceId]/ .... /[resourceType]/[resourceId]/ or /[resourceType]/[resourceId]/ .... /[resourceType]/[resourceId]/[resourceType]/[resourceId]/ .... /[resourceType]/[resourceId]/ The result of split will be in the form of [[[resourceType], [resourceId] ... ,[resourceType], [resourceId], ""] In the first case, to extract the resourceId it will the element before last ( at length -2 ) and the type will be before it ( at length -3 ) In the second case, to extract the resource type it will the element before last ( at length -2 ) */ const pathParts = resourcePath.split("/"); let id; let type; if (pathParts.length % 2 === 0) { // request in form /[resourceType]/[resourceId]/ .... /[resourceType]/[resourceId]. id = pathParts[pathParts.length - 2]; type = pathParts[pathParts.length - 3]; } else { // request in form /[resourceType]/[resourceId]/ .... /[resourceType]/. id = pathParts[pathParts.length - 3]; type = pathParts[pathParts.length - 2]; } const result = { type, objectBody: { id, self: resourcePath, }, }; return result; } /** * @hidden */ function isReadRequest(operationType) { return operationType === exports.OperationType.Read || operationType === exports.OperationType.Query; } /** * @hidden */ function sleep(time) { return new Promise((resolve) => { setTimeout(() => { resolve(); }, time); }); } /** * @hidden */ function getContainerLink(link) { return link.split("/").slice(0, 4).join("/"); } /** * @hidden */ function prepareURL(endpoint, path) { return trimSlashes(endpoint) + path; } /** * @hidden */ function trimSlashes(source) { return source.replace(trimLeftSlashes, "").replace(trimRightSlashes, ""); } /** * @hidden */ function parsePath(path) { const pathParts = []; let currentIndex = 0; const throwError = () => { throw new Error("Path " + path + " is invalid at index " + currentIndex); }; const getEscapedToken = () => { const quote = path[currentIndex]; let newIndex = ++currentIndex; for (;;) { newIndex = path.indexOf(quote, newIndex); if (newIndex === -1) { throwError(); } if (path[newIndex - 1] !== "\\") { break; } ++newIndex; } const token = path.substr(currentIndex, newIndex - currentIndex); currentIndex = newIndex + 1; return token; }; const getToken = () => { const newIndex = path.indexOf("/", currentIndex); let token = null; if (newIndex === -1) { token = path.substr(currentIndex); currentIndex = path.length; } else { token = path.substr(currentIndex, newIndex - currentIndex); currentIndex = newIndex; } token = token.trim(); return token; }; while (currentIndex < path.length) { if (path[currentIndex] !== "/") { throwError(); } if (++currentIndex === path.length) { break; } if (path[currentIndex] === '"' || path[currentIndex] === "'") { pathParts.push(getEscapedToken()); } else { pathParts.push(getToken()); } } return pathParts; } /** * @hidden */ function isResourceValid(resource, err) { // TODO: fix strictness issues so that caller contexts respects the types of the functions if (resource.id) { if (typeof resource.id !== "string") { err.message = "Id must be a string."; return false; } if (resource.id.indexOf("/") !== -1 || resource.id.indexOf("\\") !== -1 || resource.id.indexOf("?") !== -1 || resource.id.indexOf("#") !== -1) { err.message = "Id contains illegal chars."; return false; } if (resource.id[resource.id.length - 1] === " ") { err.message = "Id ends with a space."; return false; } } return true; } /** * @hidden */ function isItemResourceValid(resource, err) { // TODO: fix strictness issues so that caller contexts respects the types of the functions if (resource.id) { if (typeof resource.id !== "string") { err.message = "Id must be a string."; return false; } if (resource.id.indexOf("/") !== -1 || resource.id.indexOf("\\") !== -1 || resource.id.indexOf("#") !== -1) { err.message = "Id contains illegal chars."; return false; } } return true; } /** @hidden */ function getIdFromLink(resourceLink) { resourceLink = trimSlashes(resourceLink); return resourceLink; } /** @hidden */ function getPathFromLink(resourceLink, resourceType) { resourceLink = trimSlashes(resourceLink); if (resourceType) { return "/" + encodeURI(resourceLink) + "/" + resourceType; } else { return "/" + encodeURI(resourceLink); } } /** * @hidden */ function isStringNullOrEmpty(inputString) { // checks whether string is null, undefined, empty or only contains space return !inputString || /^\s*$/.test(inputString); } /** * @hidden */ function trimSlashFromLeftAndRight(inputString) { if (typeof inputString !== "string") { throw new Error("invalid input: input is not string"); } return inputString.replace(trimLeftSlashes, "").replace(trimRightSlashes, ""); } /** * @hidden */ function validateResourceId(resourceId) { // if resourceId is not a string or is empty throw an error if (typeof resourceId !== "string" || isStringNullOrEmpty(resourceId)) { throw new Error("Resource ID must be a string and cannot be undefined, null or empty"); } // if resource id contains illegal characters throw an error if (illegalResourceIdCharacters.test(resourceId)) { throw new Error("Illegal characters ['/', '\\', '#', '?'] cannot be used in Resource ID"); } return true; } /** * @hidden */ function validateItemResourceId(resourceId) { // if resourceId is not a string or is empty throw an error if (typeof resourceId !== "string" || isStringNullOrEmpty(resourceId)) { throw new Error("Resource ID must be a string and cannot be undefined, null or empty"); } // if resource id contains illegal characters throw an error if (illegalItemResourceIdCharacters.test(resourceId)) { throw new Error("Illegal characters ['/', '\\', '#'] cannot be used in Resource ID"); } return true; } /** * @hidden */ function getResourceIdFromPath(resourcePath) { if (!resourcePath || typeof resourcePath !== "string") { return null; } const trimmedPath = trimSlashFromLeftAndRight(resourcePath); const pathSegments = trimmedPath.split("/"); // number of segments of a path must always be even if (pathSegments.length % 2 !== 0) { return null; } return pathSegments[pathSegments.length - 1]; } /** * @hidden */ function parseConnectionString(connectionString) { const keyValueStrings = connectionString.split(";"); const { AccountEndpoint, AccountKey } = keyValueStrings.reduce((connectionObject, keyValueString) => { const [key, ...value] = keyValueString.split("="); connectionObject[key] = value.join("="); return connectionObject; }, {}); if (!AccountEndpoint || !AccountKey) { throw new Error("Could not parse the provided connection string"); } return { endpoint: AccountEndpoint, key: AccountKey, }; } /** * utility function to return copy of object to avoid encryption of original object passed * in the CRUD methods. * @hidden */ /* eslint-disable @typescript-eslint/no-explicit-any, @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-shadow, no-prototype-builtins */ function copyObject(obj) { return JSON.parse(JSON.stringify(obj, (_, value) => { if (typeof value === "bigint") { throw new Error(`BigInt type is not supported`); } return value; })); } /** * @hidden */ function createDeserializer(typeMarker) { switch (typeMarker) { case TypeMarker.Long: { // return instance return new NumberSerializer(); } case TypeMarker.Double: return new FloatSerializer(); case TypeMarker.String: return new StringSerializer(); case TypeMarker.Boolean: return new BooleanSerializer(); default: throw new Error("Invalid or Unsupported data type passed."); } } /** * @hidden * extracts the top-level path */ function extractPath(path) { const secondSlashIndex = path.indexOf("/", path.indexOf("/") + 1); return secondSlashIndex === -1 ? path : path.substring(0, secondSlashIndex); } function createSerializer(propertyValue, type) { if (type) { if (type === TypeMarker.Long) { return [TypeMarker.Long, new NumberSerializer()]; } else if (type === TypeMarker.Double) { return [TypeMarker.Double, new FloatSerializer()]; } else if (type === TypeMarker.String) { return [TypeMarker.String, new StringSerializer()]; } else if (type === TypeMarker.Boolean) { return [TypeMarker.Boolean, new BooleanSerializer()]; } else { throw new Error("Invalid or Unsupported data type passed."); } } else { switch (typeof propertyValue) { case "boolean": return [TypeMarker.Boolean, new BooleanSerializer()]; case "string": return [TypeMarker.String, new StringSerializer()]; case "object": if (propertyValue.constructor === Date) { return [TypeMarker.String, new StringSerializer()]; } throw new Error("Invalid or Unsupported data type passed."); case "number": if (!Number.isInteger(propertyValue)) { return [TypeMarker.Double, new FloatSerializer()]; } else { return [TypeMarker.Long, new NumberSerializer()]; } default: throw new Error("Invalid or Unsupported data type passed."); } } } /** * @hidden * verifies policy format version, included paths and ensures that id and partition key paths specified in the client encryption policy * for encryption are encrypted using Deterministic encryption algorithm. */ function validateClientEncryptionPolicy(clientEncryptionPolicy, partitionKey) { const policyFormatVersion = clientEncryptionPolicy.policyFormatVersion; if (policyFormatVersion < 1 || policyFormatVersion > 2) { throw new ErrorResponse("Supported versions of client encryption policy are 1 and 2."); } const paths = new Set(); // checks for duplicate paths and validates the path format and clientEncryptionKeyId for (const includedPath of clientEncryptionPolicy.includedPaths) { if (paths.has(includedPath.path)) { throw new ErrorResponse(`Duplicate path found: ${includedPath.path} in client encryption policy.`); } if (includedPath.path === undefined || includedPath.path === null || includedPath.path === "" || includedPath.path === "/") { throw new ErrorResponse("Path needs to be defined in ClientEncryptionIncludedPath."); } if (includedPath.clientEncryptionKeyId === undefined || includedPath.clientEncryptionKeyId === null || includedPath.clientEncryptionKeyId === "" || typeof includedPath.clientEncryptionKeyId !== "string") { throw new ErrorResponse("ClientEncryptionKeyId needs to be defined as string type in ClientEncryptionIncludedPath."); } if (includedPath.path[0] !== "/") { throw new ErrorResponse("Path in ClientEncryptionIncludedPath must start with '/'."); } const pathSegments = includedPath.path.split("/").filter((segment) => segment.length > 0); if (pathSegments.length > 1) { throw new ErrorResponse("Only top-level paths are currently supported for encryption"); } paths.add(includedPath.path); } // checks if id and partition key paths are encrypted using Deterministic encryption algorithm. const encryptedPaths = clientEncryptionPolicy.includedPaths; const partitionKeyPaths = partitionKey.paths.map(extractPath); let isPartitionKeyEncrypted = false; let isIdEncrypted = false; for (const encryptedPath of encryptedPaths) { if (encryptedPath.path === "/id") { isIdEncrypted = true; if (encryptedPath.encryptionType !== exports.EncryptionType.DETERMINISTIC) { throw new ErrorResponse("The '/id' property must be encrypted using Deterministic encryption."); } } if (partitionKeyPaths.includes(encryptedPath.path)) { isPartitionKeyEncrypted = true; if (encryptedPath.encryptionType !== exports.EncryptionType.DETERMINISTIC) { throw new ErrorResponse(`Path: ${encryptedPath.path} which is part of the partition key has to be encrypted with Deterministic type Encryption.`); } } } // Ensures that the policy format version is 2 if id or partition key paths are encrypted. if ((isPartitionKeyEncrypted || isIdEncrypted) && clientEncryptionPolicy.policyFormatVersion === 1) { throw new ErrorResponse("Encryption of partition key or id is only supported with policy format version 2."); } } // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. /** * @hidden */ const StatusCodes = { // Success Ok: 200, Created: 201, Accepted: 202, NoContent: 204, NotModified: 304, // Client error BadRequest: 400, Unauthorized: 401, Forbidden: 403, NotFound: 404, MethodNotAllowed: 405, RequestTimeout: 408, Conflict: 409, Gone: 410, PreconditionFailed: 412, RequestEntityTooLarge: 413, TooManyRequests: 429, RetryWith: 449, // Server Error InternalServerError: 500, ServiceUnavailable: 503, // System codes ENOTFOUND: "ENOTFOUND", // Operation pause and cancel. These are FAKE status codes for QOS logging purpose only. OperationPaused: 1200, OperationCancelled: 1201, }; /** * @hidden */ const SubStatusCodes = { Unknown: 0, // 400: Bad Request Substatus CrossPartitionQueryNotServable: 1004, IncorrectContainerRidSubstatus: 1024, PartitionKeyMismatch: 1001, // 410: StatusCodeType_Gone: substatus PartitionKeyRangeGone: 1002, CompletingSplit: 1007, // 404: NotFound Substatus ReadSessionNotAvailable: 1002, // 403: Forbidden Substatus WriteForbidden: 3, DatabaseAccountNotFound: 1008, }; // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. /** * Would be used when creating or deleting a DocumentCollection * or a User in Azure Cosmos DB database service * @hidden * Given a database id, this creates a database link. * @param databaseId - The database id * @returns A database link in the format of `dbs/{0}` * with `{0}` being a Uri escaped version of the databaseId */ function createDatabaseUri(databaseId) { databaseId = trimSlashFromLeftAndRight(databaseId); validateResourceId(databaseId); return Constants.Path.DatabasesPathSegment + "/" + databaseId; } /** * Given a database and collection id, this creates a collection link. * Would be used when updating or deleting a DocumentCollection, creating a * Document, a StoredProcedure, a Trigger, a UserDefinedFunction, or when executing a query * with CreateDocumentQuery in Azure Cosmos DB database service. * @param databaseId - The database id * @param collectionId - The collection id * @returns A collection link in the format of `dbs/{0}/colls/{1}` * with `{0}` being a Uri escaped version of the databaseId and `{1}` being collectionId * @hidden */ function createDocumentCollectionUri(databaseId, collectionId) { collectionId = trimSlashFromLeftAndRight(collectionId); validateResourceId(collectionId); return (createDatabaseUri(databaseId) + "/" + Constants.Path.CollectionsPathSegment + "/" + collectionId); } /** * Given a database and user id, this creates a user link. * Would be used when creating a Permission, or when replacing or deleting * a User in Azure Cosmos DB database service * @param databaseId - The database id * @param userId - The user id * @returns A user link in the format of `dbs/{0}/users/{1}` * with `{0}` being a Uri escaped version of the databaseId and `{1}` being userId * @hidden */ function createUserUri(databaseId, userId) { userId = trimSlashFromLeftAndRight(userId); validateResourceId(userId); return createDatabaseUri(databaseId) + "/" + Constants.Path.UsersPathSegment + "/" + userId; } /** * Given a database and collection id, this creates a collection link. * Would be used when creating an Attachment, or when replacing * or deleting a Document in Azure Cosmos DB database service * @param databaseId - The database id * @param collectionId - The collection id * @param documentId - The document id * @returns A document link in the format of * `dbs/{0}/colls/{1}/docs/{2}` wi