@odata2ts/odata-query-objects
Version:
Q-Objects are the magic sauce for the odata-query-builder and allow for renaming and type conversion
144 lines • 6.49 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.QueryObject = exports.ENUMERABLE_PROP_DEFINITION = void 0;
function getMapping(q) {
// need to use a for-in loop, because of getters which are located at the prototype level
const result = new Map();
for (let key in q) {
// @ts-ignore
const value = q[key];
if (typeof value === "object" && typeof value.getPath === "function") {
const odataName = value.getPath();
result.set(odataName, key);
}
}
return result;
}
exports.ENUMERABLE_PROP_DEFINITION = { enumerable: true };
class QueryObject {
constructor(__prefix) {
this.__prefix = __prefix;
}
__getPropMapping() {
if (!this.__propMapping) {
this.__propMapping = getMapping(this);
}
return this.__propMapping;
}
/**
* Adds the prefix of this QueryObject including a separating slash in front of the given path.
* Only applies, if this QueryObject has a prefix.
*
* @param path the path to be prefixed
* @protected
*/
withPrefix(path) {
return this.__prefix ? `${this.__prefix}/${path}` : path;
}
// public convertFromOData(odataModel: Array<object>): Array<PartialDeep<T>>;
convertFromOData(odataModel) {
if (odataModel === null || odataModel === undefined) {
return odataModel;
}
if (typeof odataModel !== "object") {
throw new Error("The model must be an object!");
}
const isList = Array.isArray(odataModel);
const models = isList ? odataModel : [odataModel];
const result = models.map((model) => {
var _a;
const typeByCi = (_a = model["@odata.type"]) === null || _a === void 0 ? void 0 : _a.replace(/^#/, "");
return Object.entries(model).reduce((collector, [key, value]) => {
let propKey = this.__getPropMapping().get(key);
let finalKey = propKey;
if (typeByCi) {
const newPropKey = this.__getPropMapping().get(`${typeByCi}/${key}`);
if (newPropKey && typeof this.__subtypeMapping !== "undefined") {
propKey = newPropKey;
finalKey = newPropKey.replace(new RegExp(`^${this.__subtypeMapping[typeByCi]}_`), "");
}
}
const prop = propKey ? this[propKey] : undefined;
if (prop && finalKey) {
// complex props
const asComplexType = prop;
if (typeof asComplexType.getEntity === "function") {
// workaround: some V2 services wrap expanded entity collections in an extra results object #125
// => we unwrap this to stay true to the generated model interfaces
const wrappedValue = value;
const sanitizedValue = asComplexType.isCollectionType() &&
wrappedValue &&
typeof wrappedValue === "object" &&
typeof wrappedValue.results === "object" &&
Array.isArray(wrappedValue.results)
? wrappedValue.results
: value;
const entity = asComplexType.getEntity();
collector[finalKey] = entity.convertFromOData(sanitizedValue);
}
// primitive props
else {
collector[finalKey] = prop.converter ? prop.converter.convertFrom(value) : value;
}
}
// be permissive here to allow passing unknown values as they are
else {
collector[key] = value;
}
return collector;
}, {});
});
return isList ? result : result[0];
}
convertToOData(userModel, failForUnknownProps = false) {
if (userModel === null || userModel === undefined) {
return userModel;
}
if (typeof userModel !== "object") {
throw new Error("The model must be an object!");
}
const isList = Array.isArray(userModel);
const models = isList ? userModel : [userModel];
const result = models.map((model) => {
var _a;
// @ts-ignore
const typeByCi = (_a = model["@odata.type"]) === null || _a === void 0 ? void 0 : _a.replace(/^#/, "");
return Object.entries(model).reduce((collector, [key, value]) => {
let prop = this[key];
let finalKey = prop === null || prop === void 0 ? void 0 : prop.getPath();
if (typeByCi && typeof this.__subtypeMapping !== "undefined") {
const qName = this.__subtypeMapping[typeByCi];
const subProp = this[`${qName}_${key}`];
if (subProp) {
prop = subProp;
finalKey = subProp.getPath().replace(new RegExp(`^${typeByCi}/`), "");
}
}
const asEntity = prop;
if (typeof (asEntity === null || asEntity === void 0 ? void 0 : asEntity.getEntity) === "function") {
const entity = asEntity.getEntity();
collector[finalKey] = entity.convertToOData(value);
}
else if (prop) {
collector[finalKey] = prop.converter ? prop.converter.convertTo(value) : value;
}
// control information is passed as is
else if (key.startsWith("@")) {
collector[key] = value;
}
else if (failForUnknownProps) {
const knownProps = [...this.__getPropMapping().values()].join(",");
throw new Error(`Property [${key}] not found (in strict mode)! Known user model props: ${knownProps}`);
}
else {
// passing unknown value as is
collector[key] = value;
}
return collector;
}, {});
});
return isList ? result : result[0];
}
}
exports.QueryObject = QueryObject;
//# sourceMappingURL=QueryObject.js.map