@elastic.io/odata-library
Version:
Re-usable OData client library
130 lines (110 loc) • 4.46 kB
JavaScript
// eslint no-restricted-syntax
const { parse, convert } = require('odata2openapi');
const request = require('request-promise');
const { convertJsonSchemaToEioSchema } = require('./jsonSchemaConversionUtil');
module.exports = class CsdlConverter {
constructor(csdlString) {
this.csdlString = csdlString;
}
async build() {
if (!this.csdlString) {
throw new Error('Cant build schema: got no csdl string!');
}
this.service = await parse(this.csdlString);
this.openApiDefinition = convert(this.service.entitySets, this.service, this.service.version);
return this;
}
async buildByMetadataUrl(metadataUrl) {
if (this.csdlString) {
throw new Error('Cant build schema by url: already got metadata string!');
}
this.csdlString = await request(metadataUrl);
return this.build();
}
getResourcesList() {
return this.service.entitySets
.map(es => ({ name: es.name, keys: es.entityType.key }));
}
getEntitySet(entitySetName) {
const entitySets = this.service.entitySets.filter(es => es.name === entitySetName);
if (entitySets.length === 0) {
throw new Error('No such name in Entity Set');
} else if (entitySets.length > 1) {
throw new Error('Entity Set name not unique');
}
return entitySets[0];
}
getKeysForObjectType(entitySetName) {
const entitySet = this.getEntitySet(entitySetName);
return entitySet.entityType.key;
}
convertCsdlString(entitySetName) {
const entitySet = this.getEntitySet(entitySetName);
const fullyQualifiedName = `${entitySet.namespace}.${entitySet.entityType.name}`;
return {
jsonSchema: convertJsonSchemaToEioSchema(fullyQualifiedName,
this.openApiDefinition.definitions),
keys: entitySet.entityType.key,
fieldsToWrapInQuotesInUrl: entitySet.entityType.properties
.filter(p => p.wrapValueInQuotesInUrls)
.map(p => p.name),
};
}
findMinorRef(entitySetName) {
let entitySets;
// eslint-disable-next-line no-restricted-syntax
for (const types of [this.service.complexTypes, this.service.entitySets,
this.service.entityTypes, this.service.enumTypes]) {
entitySets = types.filter(es => es.name === entitySetName);
if (entitySets.length !== 0) {
break;
}
}
if (entitySets.length === 0) {
throw new Error('No such name in Entity Set');
} else if (entitySets.length > 1) {
throw new Error('Entity Set name not unique');
}
const entitySet = entitySets[0];
const fullyQualifiedName = `${entitySet.namespace}.${entitySetName}`;
return convertJsonSchemaToEioSchema(fullyQualifiedName, this.openApiDefinition.definitions);
}
resolveMetadataRefs(jsonSchema, maxLevel) {
if (!maxLevel) {
maxLevel = 3; // eslint-disable-line no-param-reassign
}
return this.resolveMetadataRefsStep(jsonSchema, [], maxLevel, 0);
}
resolveMetadataRefsStep(jsonSchema, stack, maxLevel, currentLevel) {
const jsonSchemaCopy = JSON.parse(JSON.stringify(jsonSchema));
if (currentLevel >= maxLevel) {
return jsonSchemaCopy;
}
Object.keys(jsonSchema.properties)
.forEach((key) => {
const property = jsonSchema.properties[key];
if (property.type === 'object' && property.$ref) {
const refEntityName = property.$ref.match('[a-zA-Z]+$')[0];
if (stack.indexOf(refEntityName) === -1) {
stack.push(refEntityName);
let schema = this.findMinorRef(refEntityName);
schema = this.resolveMetadataRefsStep(schema, stack, maxLevel, currentLevel + 1);
jsonSchemaCopy.properties[key].properties = schema.properties;
stack.splice(stack.indexOf(refEntityName), 1);
}
delete jsonSchemaCopy.properties[key].$ref;
} else if (property.type === 'array' && property.items.$ref) {
const refEntityName = property.items.$ref.match('[a-zA-Z]+$')[0];
if (stack.indexOf(refEntityName) === -1) {
stack.push(refEntityName);
let schema = this.findMinorRef(refEntityName);
schema = this.resolveMetadataRefsStep(schema, stack, maxLevel, currentLevel + 1);
jsonSchemaCopy.properties[key].items = schema;
stack.splice(stack.indexOf(refEntityName), 1);
}
delete jsonSchemaCopy.properties[key].items.$ref;
}
});
return jsonSchemaCopy;
}
};