botbuilder-azure
Version:
Azure extensions for Microsoft BotBuilder.
72 lines • 3.78 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.CosmosDbKeyEscape = void 0;
/**
* @module botbuilder-azure
*/
/**
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License.
*/
const crypto = require("crypto");
// eslint-disable-next-line @typescript-eslint/no-namespace
var CosmosDbKeyEscape;
(function (CosmosDbKeyEscape) {
// Older libraries had a max key length of 255.
// The limit is now 1023. In this library, 255 remains the default for backwards compat.
// To override this behavior, and use the longer limit, set cosmosDbPartitionedStorageOptions.compatibilityMode to false.
// https://docs.microsoft.com/en-us/azure/cosmos-db/concepts-limits#per-item-limits
const maxKeyLength = 255;
const illegalKeys = ['\\', '?', '/', '#', '\t', '\n', '\r', '*'];
const illegalKeyCharacterReplacementMap = illegalKeys.reduce((map, c) => {
map.set(c, `*${c.charCodeAt(0).toString(16)}`);
return map;
}, new Map());
/**
* Converts the key into a DocumentID that can be used safely with CosmosDB.
* The following characters are restricted and cannot be used in the Id property: '/', '\', '?', '#'
* More information at https://docs.microsoft.com/en-us/dotnet/api/microsoft.azure.documents.resource.id?view=azure-dotnet#remarks
*
* @param key The provided key to be escaped.
* @param keySuffix The string to add a the end of all RowKeys.
* @param compatibilityMode True if keys should be truncated in order to support previous CosmosDb
* max key length of 255. This behavior can be overridden by setting cosmosDbPartitionedStorageOptions.compatibilityMode to false.
* @returns An escaped key that can be used safely with CosmosDB.
*/
function escapeKey(key, keySuffix, compatibilityMode) {
if (!key) {
throw new Error("The 'key' parameter is required.");
}
const keySplitted = key.split('');
const firstIllegalCharIndex = keySplitted.findIndex((c) => illegalKeys.some((i) => i === c));
// If there are no illegal characters return immediately and avoid any further processing/allocations
if (firstIllegalCharIndex === -1) {
return truncateKey(`${key}${keySuffix || ''}`, compatibilityMode);
}
const sanitizedKey = keySplitted.reduce((result, c) => result + (illegalKeyCharacterReplacementMap.has(c) ? illegalKeyCharacterReplacementMap.get(c) : c), '');
return truncateKey(`${sanitizedKey}${keySuffix || ''}`, compatibilityMode);
/**
* Truncates the key if it exceeds the max key length to have backwards compatibility with older libraries.
*
* @param key The key to be truncated.
* @param truncateKeysForCompatibility True if keys should be truncated in order to support previous CosmosDb
* max key length of 255. False to override this behavior using the longer limit.
* @returns The resulting key.
*/
function truncateKey(key, truncateKeysForCompatibility) {
if (truncateKeysForCompatibility === false) {
return key;
}
if (key.length > maxKeyLength) {
const hash = crypto.createHash('sha256');
hash.update(key);
// combine truncated key with hash of self for extra uniqueness
const hex = hash.digest('hex');
key = key.substr(0, maxKeyLength - hex.length) + hex;
}
return key;
}
}
CosmosDbKeyEscape.escapeKey = escapeKey;
})(CosmosDbKeyEscape = exports.CosmosDbKeyEscape || (exports.CosmosDbKeyEscape = {}));
//# sourceMappingURL=cosmosDbKeyEscape.js.map
;