UNPKG

pailingual-odata

Version:

TypeScript client for OData v4 services

233 lines (232 loc) 8.73 kB
import { EdmEntityType, EdmEnumType } from "./metadata"; import { startsWith, endsWith } from "./utils"; var guidRE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i; var converters = { "Edm.String": { toEdm: function (v, forUri) { return forUri ? ("'" + v.toString().replace("'", "''").replace("/", "%2F") + "'") : v; } }, "Edm.Guid": { toEdm: function (v) { if (v.match(guidRE)) return v; throw new Error("Value '" + v + "' not parsed as Guid"); } }, "Edm.DateTimeOffset": { toEdm: function (v) { return v.toISOString(); }, fromEdm: function (v) { return new Date(v); } }, "Edm.Boolean": { toEdm: function (v) { return v ? "true" : "false"; } } }; var formatters = {}; export function addFormatter(formatter) { if (!formatter || !formatter.contentType || !formatter.serialize || !formatter.deserialize) throw new Error("All formatter properties is required"); formatters[formatter.contentType] = formatter; } export function getFormatter(contentType) { var f = formatters[contentType]; if (!f) throw new Error("Not supported format: " + contentType); return f; } addFormatter({ contentType: "application/json", serialize: jsonSerialize, deserialize: jsonDeserialize }); function enumMemberByValue(type, value) { for (var member in type.members) if (type.members[member] === value) return member; } function jsonSerialize(payload, metadata, options) { if (options === void 0) { options = {}; } var metadataMap = new MapObjToEntityType(); metadataMap.set(payload, metadata); var otMetadata = new EdmEntityType("$$~~openType~~$$", {}); otMetadata.openType = true; return JSON.stringify(payload, function (k, v) { if (!k || Array.isArray(this)) return v; var currentMetadata = metadataMap.get(this); if (currentMetadata != null) { var propMD = currentMetadata.properties[k] || currentMetadata.navProperties[k]; var valueType = propMD && propMD.type || ((currentMetadata.openType) ? otMetadata : undefined); if (!valueType) { throw new Error("Property '" + k + "' not found in metadata"); } if (valueType instanceof EdmEntityType) { if (Array.isArray(v)) for (var _i = 0, v_1 = v; _i < v_1.length; _i++) { var item = v_1[_i]; metadataMap.set(item, valueType); } else if (v != null) metadataMap.set(v, valueType); return v; } else { return convertToEdmValue(this[k], propMD.type, false) || v; } } throw new Error("Metadata for object not found"); }); } export function serializeValue(value, type, forUri, opt) { if (value == null) return forUri ? "null" : null; return convertToEdmValue(value, type, forUri, opt) || value.toString(); } function convertToEdmValue(value, type, forUri, opt) { if (opt === void 0) { opt = {}; } if (value == null) return null; if (type instanceof EdmEnumType) { var member = enumMemberByValue(type, value); if (member) { if (forUri) { member = "'" + member + "'"; if (!opt.enumPrefixFree) member = type.getFullName() + member; } return member; } throw new Error("Value '" + value + "' not found in enum '" + type.name + " '"); } else { var converter = converters[type]; if (converter && converter.toEdm) return converter.toEdm(value, forUri, opt); return null; } } function convertFromEdmValue(value, type, options) { var converter = converters[type]; if (converter && converter.fromEdm) return converter.fromEdm(value, options); return null; } var ODATA_CONTEXT = "@odata.context"; var ODATA_COUNT = "@odata.count"; var ODATA_TYPE = "@odata.type"; function jsonDeserialize(response, apiMetadata, options) { var rawData = JSON.parse(response); var context = rawData[ODATA_CONTEXT]; if (context) { context = context.split("#")[1]; var count = rawData[ODATA_COUNT]; var isEntity = endsWith(context, "$entity"); context = context.replace(/\/\$entity$/, ""); var type_1 = getSourceType(context, apiMetadata); if (!isEntity && Array.isArray(rawData.value)) { var value = rawData.value.map(function (v) { return convertObj(v, type_1, apiMetadata, options); }); if (count != null) return { count: count, value: value }; return value; } else return convertObj(rawData, type_1, apiMetadata, options); } } function convertObj(obj, type, apiMetadata, options) { if (obj != null) { if (Array.isArray(obj)) return obj.map(function (v) { return convertObj(v, type, apiMetadata, options); }); if (obj[ODATA_TYPE]) { var typeName = obj[ODATA_TYPE].substr(1); type = apiMetadata.getEdmTypeMetadata(typeName); if (type == null) throw new Error("Metadata for type '" + typeName + "' not found."); } if (typeof type == "string") { if (typeof obj == "object") obj = obj.value; return convertFromEdmValue(obj, type, options) || obj; } else { var res = void 0; if (type instanceof EdmEnumType) { var res_1 = type.members[obj]; if (!res_1) throw new Error("Member '" + obj + "' not found in enum '" + type.name + "'"); return res_1; } else { var entityType = type; res = {}; var edmProps = getEdmProperties(entityType); for (var propName in obj) { var edmPropertyType = edmProps[propName]; if (edmPropertyType) res[propName] = convertObj(obj[propName], edmPropertyType, apiMetadata, options); else if (!startsWith(propName, "@") && entityType.openType == true) res[propName] = obj[propName]; } } return res; } } return null; } function getEdmProperties(type) { var res = type.baseType ? getEdmProperties(type.baseType) : {}; for (var prop in type.properties) { res[prop] = type.properties[prop].type; } for (var prop in type.navProperties) { res[prop] = type.navProperties[prop].type; } return res; } function getSourceType(source, apiMetadata) { if (startsWith(source, "Collection")) source = source.substring("Collection".length + 1, source.length - 1); var pos = source.indexOf("("); if (pos > -1) source = source.substring(0, pos); var parts = source.split("/"); source = parts[parts.length - 1]; var es = apiMetadata.entitySets[source]; if (!es) { var dotPos = source.lastIndexOf('.'); if (dotPos > -1) { var ns = source.substr(0, dotPos); var type = source.substr(dotPos + 1); if (ns == "Edm") //Primitive type return source; var nsObj = apiMetadata.namespaces[ns]; if (nsObj && nsObj.types[type]) return nsObj.types[type]; } } return es; } var MapObjToEntityType = /** @class */ (function () { function MapObjToEntityType() { this.__keys = []; this.__values = []; } MapObjToEntityType.prototype.get = function (key) { if (key) { var index = this.__keys.indexOf(key); if (index > -1) return this.__values[index]; } }; MapObjToEntityType.prototype.set = function (key, entityType) { if (key == null) throw new Error("Key must be set"); var index = this.__keys.indexOf(key); if (index == -1) index = this.__keys.push(key) - 1; this.__values[index] = entityType; }; return MapObjToEntityType; }());