pailingual-odata
Version:
TypeScript client for OData v4 services
418 lines (417 loc) • 19.3 kB
JavaScript
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return extendStatics(d, b);
}
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
import { startsWith, endsWith } from "./utils";
var COLLECTION_TYPE_PREFIX = "Collection(";
export var EdmTypes;
(function (EdmTypes) {
EdmTypes["Int32"] = "Edm.Int32";
EdmTypes["Int16"] = "Edm.Int16";
EdmTypes["Boolean"] = "Edm.Boolean";
EdmTypes["String"] = "Edm.String";
EdmTypes["Single"] = "Edm.Single";
EdmTypes["Guid"] = "Edm.Guid";
EdmTypes["DateTimeOffset"] = "Edm.DateTimeOffset";
EdmTypes["Date"] = "Edm.Date";
EdmTypes["Double"] = "Edm.Double";
EdmTypes["TimeOfDay"] = "Edm.TimeOfDay";
EdmTypes["Decimal"] = "Edm.Decimal";
EdmTypes["Unknown"] = "Unknown";
})(EdmTypes || (EdmTypes = {}));
var EdmEntityType = /** @class */ (function () {
function EdmEntityType(name, properties, navProperties, keys, baseType, openType) {
if (navProperties === void 0) { navProperties = {}; }
var _this = this;
this.name = name;
this.properties = properties;
this.navProperties = navProperties;
this.keys = keys;
this.baseType = baseType;
this.openType = openType;
this.getFullName = function () { return getFullName(_this); };
}
return EdmEntityType;
}());
export { EdmEntityType };
var EdmComplexType = /** @class */ (function (_super) {
__extends(EdmComplexType, _super);
function EdmComplexType() {
return _super !== null && _super.apply(this, arguments) || this;
}
return EdmComplexType;
}(EdmEntityType));
export { EdmComplexType };
var EdmEnumType = /** @class */ (function () {
function EdmEnumType(name, members) {
var _this = this;
this.name = name;
this.members = members;
this.getFullName = function () { return getFullName(_this); };
}
return EdmEnumType;
}());
export { EdmEnumType };
var EdmEntityTypeReference = /** @class */ (function () {
function EdmEntityTypeReference(type, nullable, collection) {
if (nullable === void 0) { nullable = true; }
if (collection === void 0) { collection = false; }
this.type = type;
this.nullable = nullable;
this.collection = collection;
}
EdmEntityTypeReference.fromTypeReference = function (typeReference) {
if (typeReference.type instanceof EdmEntityType) {
return typeReference;
}
throw new Error("Instance must be reference to EdmEntityType");
};
return EdmEntityTypeReference;
}());
export { EdmEntityTypeReference };
var EdmTypeReference = /** @class */ (function () {
function EdmTypeReference(type, nullable, collection) {
if (nullable === void 0) { nullable = true; }
if (collection === void 0) { collection = false; }
this.type = type;
this.nullable = nullable;
this.collection = collection;
}
return EdmTypeReference;
}());
export { EdmTypeReference };
;
var OperationMetadata = /** @class */ (function () {
function OperationMetadata(name, isAction, parameters, returnType, bindingTo) {
var _this = this;
this.name = name;
this.isAction = isAction;
this.parameters = parameters;
this.returnType = returnType;
this.bindingTo = bindingTo;
this.getFullName = function () { return getFullName(_this); };
}
return OperationMetadata;
}());
export { OperationMetadata };
function getFullName(obj) {
if (obj.namespace)
return [obj.namespace.name, obj.name].join(".");
return obj.name;
}
var Namespace = /** @class */ (function () {
function Namespace(name) {
this.name = name;
this.operations = [];
this.types = {};
}
Namespace.prototype.addTypes = function () {
var types = [];
for (var _i = 0; _i < arguments.length; _i++) {
types[_i] = arguments[_i];
}
for (var _a = 0, types_1 = types; _a < types_1.length; _a++) {
var type = types_1[_a];
type.namespace = this;
this.types[type.name] = type;
}
};
Namespace.prototype.addOperations = function () {
var operations = [];
for (var _i = 0; _i < arguments.length; _i++) {
operations[_i] = arguments[_i];
}
for (var _a = 0, operations_1 = operations; _a < operations_1.length; _a++) {
var operation = operations_1[_a];
operation.namespace = this;
this.operations.push(operation);
}
};
return Namespace;
}());
export { Namespace };
;
var __metadataCache = {};
export function loadMetadata(apiRoot, options, cache) {
if (cache === void 0) { cache = true; }
if (endsWith(apiRoot, "/"))
apiRoot = apiRoot.substr(0, apiRoot.length - 1);
var normalizedApiRoot = apiRoot.toLowerCase(), res = __metadataCache[normalizedApiRoot];
if (res == null || !cache) {
return ApiMetadata.loadAsync(apiRoot, options)
.then(function (md) {
if (cache)
__metadataCache[normalizedApiRoot] = md;
return md;
});
}
return Promise.resolve(res);
}
var ApiMetadata = /** @class */ (function () {
function ApiMetadata(apiRoot, containerName, namespaces, entitySets, singletons) {
if (namespaces === void 0) { namespaces = {}; }
if (entitySets === void 0) { entitySets = {}; }
if (singletons === void 0) { singletons = {}; }
this.apiRoot = apiRoot;
this.containerName = containerName;
this.namespaces = namespaces;
this.entitySets = entitySets;
this.singletons = singletons;
}
ApiMetadata.loadFromXml = function (apiRoot, metadataXml) {
var parser = new DOMParser();
var metadataDoc = parser.parseFromString(metadataXml, "text/xml");
var namespaces = ApiMetadata.parseEntityTypes(metadataDoc);
var entitySets = {};
var singletons = {};
var container = metadataDoc.querySelector("Schema>EntityContainer");
var containerName = container && getRequiredAttributeValue(container, "Name");
if (container) {
var list = container.querySelectorAll("EntitySet,Singleton");
for (var i = 0; i < list.length; i++) {
var e = list.item(i);
var isSingleton = e.tagName.toUpperCase() === "SINGLETON";
var name_1 = getRequiredAttributeValue(e, "Name");
var typeName = getRequiredAttributeValue(e, isSingleton ? "Type" : "EntityType");
var target = isSingleton ? singletons : entitySets;
target[name_1] = ApiMetadata.getEntitySetMetadata(typeName, namespaces);
}
}
var list3 = metadataDoc.querySelectorAll("Schema>Function,Schema>Action");
for (var i = 0; i < list3.length; i++) {
var e = list3.item(i);
var metadata = ApiMetadata.parseOperationMetadata(e, namespaces);
var namespaceName = getRequiredAttributeValue(e.parentElement, "Namespace");
if (!namespaces[namespaceName])
namespaces[namespaceName] = new Namespace(namespaceName);
namespaces[namespaceName].addOperations(metadata);
}
return new ApiMetadata(apiRoot, containerName, namespaces, entitySets, singletons);
};
ApiMetadata.loadAsync = function (apiRoot, options) {
return __awaiter(this, void 0, void 0, function () {
var uri, opt, fetchApi, credentials, response, _a, _b;
return __generator(this, function (_c) {
switch (_c.label) {
case 0:
uri = apiRoot + "/$metadata";
opt = options || {};
fetchApi = opt.fetch || fetch;
credentials = opt.credentials;
return [4 /*yield*/, fetchApi(uri, { credentials: credentials })];
case 1:
response = _c.sent();
_a = this.loadFromXml;
_b = [apiRoot];
return [4 /*yield*/, response.text()];
case 2: return [2 /*return*/, _a.apply(this, _b.concat([_c.sent()]))];
}
});
});
};
ApiMetadata.parseEntityTypes = function (metadataDoc) {
var namespaces = {};
var entityTypes = [];
var list = metadataDoc.querySelectorAll("Schema>ComplexType,Schema>EntityType,Schema>EnumType");
var _loop_1 = function () {
var e = list.item(i);
var getOrAddEdmEntityType = function (namespace, name) {
var namespaceMD = namespaces[namespace];
if (!namespaceMD)
namespaces[namespace] = namespaceMD = new Namespace(namespace);
var typeMetadata = namespaceMD.types[name];
if (!typeMetadata) {
typeMetadata = e.tagName.toLowerCase() == "complextype"
? new EdmComplexType(name, {})
: new EdmEntityType(name, {});
namespaceMD.addTypes(typeMetadata);
}
return typeMetadata;
};
var ns = getRequiredAttributeValue(e.parentElement, "Namespace");
var name_2 = getRequiredAttributeValue(e, "Name");
if (!(ns in namespaces))
namespaces[ns] = new Namespace(ns);
if (e.tagName.toLowerCase() === "enumtype") {
var enumType = new EdmEnumType(name_2, ApiMetadata.parseEnumMembers(e));
namespaces[ns].addTypes(enumType);
}
else {
var typeMetadata = getOrAddEdmEntityType(ns, name_2);
typeMetadata.openType = getAttributeBoolValue(e, "OpenType");
var baseType = getAttributeValue(e, "BaseType");
if (baseType) {
var baseTypeNS = baseType.substring(0, baseType.lastIndexOf("."));
var baseTypeName = baseType.substr(baseTypeNS.length + 1);
var bt = getOrAddEdmEntityType(baseTypeNS, baseTypeName);
typeMetadata.baseType = bt;
}
entityTypes.push({ element: e, typeMetadata: typeMetadata });
}
};
for (var i = 0; i < list.length; i++) {
_loop_1();
}
for (var _i = 0, entityTypes_1 = entityTypes; _i < entityTypes_1.length; _i++) {
var e = entityTypes_1[_i];
Object.assign(e.typeMetadata, ApiMetadata.getEntityTypeProperties(e.element, namespaces));
e.typeMetadata.keys = this.parseEntityKeys(e.element);
}
return namespaces;
};
ApiMetadata.parseEntityKeys = function (typeElement) {
var res = new Array();
var list = typeElement.querySelectorAll("Key>PropertyRef");
for (var i = 0; i < list.length; i++) {
res.push(getRequiredAttributeValue(list.item(i), "Name"));
}
return res;
};
ApiMetadata.parseEnumMembers = function (element) {
var res = {};
var list = element.querySelectorAll("Member");
for (var i = 0; i < list.length; i++) {
var e = list.item(i);
var name_3 = getRequiredAttributeValue(e, "Name");
var rawValue = getRequiredAttributeValue(e, "Value");
res[name_3] = (rawValue.match(/\d/)) ? parseInt(rawValue) : rawValue;
}
return res;
};
ApiMetadata.getEntityTypeProperties = function (typeElement, namespaces) {
var properties = {};
var navProperties = {};
var list = typeElement.querySelectorAll("Property,NavigationProperty");
for (var i = 0; i < list.length; i++) {
var e = list.item(i);
var name_4 = getRequiredAttributeValue(e, "Name");
var metadata = ApiMetadata.parseType(e, namespaces);
if (e.tagName.toLowerCase() == "property")
properties[name_4] = metadata;
else
navProperties[name_4] = EdmEntityTypeReference.fromTypeReference(metadata);
}
return { properties: properties, navProperties: navProperties };
};
ApiMetadata.prototype.getEntitySetMetadata = function (typeName) {
return ApiMetadata.getEntitySetMetadata(typeName, this.namespaces);
};
ApiMetadata.getEntitySetMetadata = function (typeName, namespaces) {
var res = ApiMetadata.getEdmTypeMetadata(typeName, namespaces);
if (res instanceof EdmEntityType)
return res;
throw new Error("EntitySet item type must be entity");
};
ApiMetadata.prototype.getEdmTypeMetadata = function (typeName) {
return ApiMetadata.getEdmTypeMetadata(typeName, this.namespaces);
};
ApiMetadata.getEdmTypeMetadata = function (typeName, namespaces) {
if (startsWith(typeName, COLLECTION_TYPE_PREFIX))
typeName = typeName.substring(COLLECTION_TYPE_PREFIX.length, typeName.length - 1);
var namespace = typeName.substring(0, typeName.lastIndexOf("."));
var typeNameNoNs = typeName.substr(namespace.length + 1);
if (namespace == "Edm") {
var t = EdmTypes[typeNameNoNs];
if (!t)
throw new Error("Not registred Edm type: " + typeNameNoNs);
return t;
}
var nsMeta = namespaces[namespace];
if (!nsMeta)
throw new Error("Namespace '" + namespace + "' not found");
var typeElement = nsMeta.types[typeNameNoNs];
return typeElement;
};
ApiMetadata.parseOperationMetadata = function (operationElement, namespaces) {
var isAction = operationElement.tagName.toLowerCase() === "action";
var name = getRequiredAttributeValue(operationElement, "Name");
var returnTypeElement = operationElement.querySelector("ReturnType");
var returnType = returnTypeElement
? ApiMetadata.parseType(returnTypeElement, namespaces)
: undefined;
var parameters = new Array();
var bindingTo;
var list = operationElement.querySelectorAll("Parameter");
for (var i = 0; i < list.length; i++) {
var e = list.item(i);
var type = ApiMetadata.parseType(e, namespaces);
var name_5 = getRequiredAttributeValue(e, "Name");
if (getAttributeBoolValue(operationElement, "IsBound") && !bindingTo)
bindingTo = EdmEntityTypeReference.fromTypeReference(type);
else
parameters.push({ name: name_5, type: type });
}
return new OperationMetadata(name, isAction, parameters, returnType, bindingTo);
};
ApiMetadata.parseType = function (element, namespaces) {
var typeName = getRequiredAttributeValue(element, "Type");
var collection = startsWith(typeName, COLLECTION_TYPE_PREFIX);
if (collection)
typeName = typeName.substring(COLLECTION_TYPE_PREFIX.length, typeName.length - 1);
var typeMetadata = ApiMetadata.getEdmTypeMetadata(typeName, namespaces);
var res = new EdmTypeReference(typeMetadata, true, collection);
res.nullable = getAttributeBoolValue(element, "Nullable") != false;
return res;
};
return ApiMetadata;
}());
export { ApiMetadata };
function getRequiredAttributeValue(element, attrName) {
return getAttributeValue(element, attrName) || (function () {
throw new Error("Metadata: Attribute '" + attrName + "' in element '" + element.tagName + "' not found ");
})();
}
function getAttributeBoolValue(element, attrName) {
var r = getAttributeValue(element, attrName);
if (r != undefined)
return r.toLowerCase() == "true";
}
function getAttributeValue(element, attrName) {
var attr = element.attributes.getNamedItem(attrName);
if (attr)
return attr.value;
}