// Copyright (c) Microsoft Corporation. // Licensed under the MIT license. import { __rest } from "tslib"; import { base64Decode, base64Encode } from "./utils/bufferSerializer"; import { truncatedISO8061Date } from "./utils/truncateISO8061Date"; const propertyCaseMap = new Map([ ["PartitionKey", "partitionKey"], ["RowKey", "rowKey"], ["odata.etag", "etag"], ["Timestamp", "timestamp"], ]); const Edm = { Binary: "Edm.Binary", Boolean: "Edm.Boolean", DateTime: "Edm.DateTime", Double: "Edm.Double", Guid: "Edm.Guid", Int32: "Edm.Int32", Int64: "Edm.Int64", String: "Edm.String", }; function serializePrimitive(value) { const serializedValue = { value }; if (value === undefined || value === null || typeof value === "boolean" || typeof value === "string" || typeof value === "number") { serializedValue.value = value; } else if (typeof value === "bigint") { serializedValue.value = value.toString(); serializedValue.type = Edm.Int64; } else if (value instanceof Date) { serializedValue.value = value; serializedValue.type = Edm.DateTime; } else if (value instanceof Uint8Array) { serializedValue.value = base64Encode(value); serializedValue.type = Edm.Binary; } else { throw new Error(`Unknown EDM type ${typeof value}`); } return serializedValue; } function serializeObject(obj) { const serializedValue = { value: obj.value }; if (obj.type === "Boolean" || obj.type === "DateTime" || obj.type === "Double" || obj.type === "Guid" || obj.type === "Int32" || obj.type === "Int64" || obj.type === "String" || obj.type === "Binary") { serializedValue.value = obj.value; serializedValue.type = Edm[obj.type]; } else { throw new Error(`Unknown EDM type ${typeof obj.value}`); } return serializedValue; } function getSerializedValue(value) { if (typeof value === "object" && (value === null || value === void 0 ? void 0 : value.value) !== undefined && (value === null || value === void 0 ? void 0 : value.type) !== undefined) { return serializeObject(value); } else { return serializePrimitive(value); } } function translatePropertyNameForSerialization(propertyName) { for (const [original, internal] of propertyCaseMap) { if (internal === propertyName) { return original; } } return propertyName; } export function serialize(obj) { const serialized = {}; for (const [propertyName, propertyValue] of Object.entries(obj)) { const transformedKey = translatePropertyNameForSerialization(propertyName); const serializedVal = getSerializedValue(propertyValue); serialized[transformedKey] = serializedVal.value; if (serializedVal.type) { serialized[`${transformedKey}@odata.type`] = serializedVal.type; } } return serialized; } function getTypedObject(value, type, disableTypeConversion) { switch (type) { case Edm.Boolean: return disableTypeConversion ? { value, type: "Boolean" } : value; case Edm.Double: return disableTypeConversion ? { value, type: "Double" } : value; case Edm.Int32: return disableTypeConversion ? { value, type: "Int32" } : value; case Edm.String: return disableTypeConversion ? { value, type: "String" } : value; case Edm.DateTime: return disableTypeConversion ? { value, type: "DateTime" } : new Date(value); case Edm.Int64: return disableTypeConversion ? { value, type: "Int64" } : BigInt(value); case Edm.Guid: return { value, type: "Guid" }; case Edm.Binary: return disableTypeConversion ? { value, type: "Binary" } : base64Decode(value); default: throw new Error(`Unknown EDM type ${type}`); } } export function deserialize(obj, disableTypeConversion = false) { var _a; const deserialized = {}; for (const [key, value] of Object.entries(obj)) { if (key.indexOf("@odata.type") === -1) { const transformedKey = (_a = propertyCaseMap.get(key)) !== null && _a !== void 0 ? _a : key; let typedValue = value; if (`${key}@odata.type` in obj) { const type = obj[`${key}@odata.type`]; typedValue = getTypedObject(value, type, disableTypeConversion); } else if (disableTypeConversion && ["number", "string", "boolean"].includes(typeof value)) { // The service, doesn't return type metadata for number, strings or booleans // if automatic type conversion is disabled we'll infer the EDM object typedValue = inferTypedObject(key, value); } deserialized[transformedKey] = typedValue; } } return deserialized; } function inferTypedObject(propertyName, value) { // We need to skip service metadata fields such as partitionKey and rowKey and use the same value returned by the service if (propertyCaseMap.has(propertyName)) { return value; } switch (typeof value) { case "boolean": return { value: String(value), type: "Boolean" }; case "number": return getTypedNumber(value); case "string": return { value, type: "String" }; default: return value; } } /** * Returns the number when typeConversion is enabled or the EDM object with the correct number format Double or Int32 if disabled */ function getTypedNumber(value) { const valueStr = String(value); if (Number.isSafeInteger(value)) { return { value: valueStr, type: "Int32" }; } else { return { value: valueStr, type: "Double" }; } } export function deserializeObjectsArray(objArray, disableTypeConversion) { return objArray.map((obj) => deserialize(obj, disableTypeConversion)); } /** * For ACL endpoints the Tables Service takes an ISO Date without decimals however * serializing a JavaScript date gives us a date with decimals 2021-07-08T09:10:09.000Z * which makes the XML request body invalid, these 2 functions serialize and deserialize the * dates so that they are in the expected format */ export function serializeSignedIdentifiers(signedIdentifiers) { return signedIdentifiers.map((acl) => { const { id, accessPolicy } = acl; const _a = accessPolicy !== null && accessPolicy !== void 0 ? accessPolicy : {}, { start, expiry } = _a, rest = __rest(_a, ["start", "expiry"]); const serializedStart = start ? truncatedISO8061Date(start, false /** withMilliseconds */) : undefined; const serializedExpiry = expiry ? truncatedISO8061Date(expiry, false /** withMilliseconds */) : undefined; return { id, accessPolicy: Object.assign(Object.assign(Object.assign({}, (serializedExpiry && { expiry: serializedExpiry })), (serializedStart && { start: serializedStart })), rest), }; }); } export function deserializeSignedIdentifier(signedIdentifiers) { return signedIdentifiers.map((si) => { const { id, accessPolicy } = si; const _a = accessPolicy !== null && accessPolicy !== void 0 ? accessPolicy : {}, { start, expiry } = _a, restAcl = __rest(_a, ["start", "expiry"]); const deserializedStart = start ? new Date(start) : undefined; const deserializedExpiry = expiry ? new Date(expiry) : undefined; return { id, accessPolicy: Object.assign(Object.assign(Object.assign({}, (deserializedExpiry && { expiry: deserializedExpiry })), (deserializedStart && { start: deserializedStart })), restAcl), }; }); } export function serializeQueryOptions(query) { const { select } = query, queryOptions = __rest(query, ["select"]); const mappedQuery = Object.assign({}, queryOptions); // Properties that are always returned by the service but are not allowed in select const excludeFromSelect = ["etag", "odata.etag"]; if (select) { mappedQuery.select = select .filter((p) => !excludeFromSelect.includes(p)) .map(translatePropertyNameForSerialization) .join(","); } return mappedQuery; } //# sourceMappingURL=serialization.js.map