From 3ede978f8c082bf2afbfbedbce1c9b7779620b71 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Fri, 29 Aug 2025 16:36:43 +0000 Subject: [PATCH 1/3] Checkpoint before follow-up message Co-authored-by: web.88002 --- jest.config.js | 20 +- lib/compile/csdl2openapi.backup.js | 2660 ++++++++++++++++++++ lib/compile/csdl2openapi.js | 1507 +---------- lib/compile/modules/builders/index.js | 15 + lib/compile/modules/builders/parameters.js | 332 +++ lib/compile/modules/builders/paths.js | 299 +++ lib/compile/modules/builders/responses.js | 287 +++ lib/compile/modules/utils/naming.js | 15 +- 8 files changed, 3648 insertions(+), 1487 deletions(-) create mode 100644 lib/compile/csdl2openapi.backup.js create mode 100644 lib/compile/modules/builders/index.js create mode 100644 lib/compile/modules/builders/parameters.js create mode 100644 lib/compile/modules/builders/paths.js create mode 100644 lib/compile/modules/builders/responses.js diff --git a/jest.config.js b/jest.config.js index 9659f70..7d83e92 100644 --- a/jest.config.js +++ b/jest.config.js @@ -1,23 +1,11 @@ module.exports = { - preset: 'ts-jest', testEnvironment: 'node', - moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'], - testMatch: ['**/test/**/*.test.(ts|js)'], - transform: { - '^.+\\.ts$': 'ts-jest', - '^.+\\.js$': 'babel-jest', - }, + moduleFileExtensions: ['js', 'json', 'node'], + testMatch: ['**/test/**/*.test.js'], collectCoverageFrom: [ - 'lib/**/*.{js,ts}', + 'lib/**/*.js', '!lib/**/*.d.ts', ], coverageDirectory: 'coverage', - coverageReporters: ['text', 'lcov', 'html'], - globals: { - 'ts-jest': { - tsconfig: { - allowJs: true, - }, - }, - }, + coverageReporters: ['text', 'lcov', 'html'] }; \ No newline at end of file diff --git a/lib/compile/csdl2openapi.backup.js b/lib/compile/csdl2openapi.backup.js new file mode 100644 index 0000000..cb9e605 --- /dev/null +++ b/lib/compile/csdl2openapi.backup.js @@ -0,0 +1,2660 @@ +/** + * Converts OData CSDL JSON to OpenAPI 3.0.2 +*/ +const cds = require('@sap/cds'); +var pluralize = require('pluralize') +const DEBUG = cds.debug('openapi'); // Initialize cds.debug with the 'openapi' + +// Import modularized components +const constants = require('./modules/constants'); +const { nameParts, isIdentifier, splitName, namespaceQualifiedName, enumMember } = require('./modules/utils/naming'); +const validators = require('./modules/validators'); +const { + pathValuePrefix, + pathValueSuffix, + navigationPropertyPath, + propertyPath, + navigationPaths, + navigationPathMap, + primitivePaths, + buildKeyParameters, + buildPathWithKeys +} = require('./modules/builders/paths'); +const { + addQueryOptions, + optionTop, + optionSkip, + optionCount, + optionFilter, + optionOrderBy, + optionSearch, + optionSelect, + optionExpand, + buildComponentParameters +} = require('./modules/builders/parameters'); +const { + collectionResponse, + entityResponse, + operationResponse, + errorResponse, + countResponse, + batchResponse, + buildStandardResponses, + getTypeSchema, + getEdmTypeSchema, + withETag +} = require('./modules/builders/responses'); + + +//TODO +// - Core.Example for complex types +// - reduce number of loops over schemas +// - inject $$name into each model element to make parameter passing easier? +// - allow passing additional files for referenced documents +// - delta: headers Prefer and Preference-Applied +// - inline definitions for Edm.* to make OpenAPI documents self-contained +// - both "clickable" and freestyle $expand, $select, $orderby - does not work yet, open issue for OpenAPI UI +// - system query options for actions/functions/imports depending on $Collection +// - 200 response for PATCH +// - ETag for GET / If-Match for PATCH and DELETE depending on @Core.OptimisticConcurrency +// - CountRestrictions for GET collection-valued (containment) navigation - https://issues.oasis-open.org/browse/ODATA-1300 +// - InsertRestrictions/NonInsertableProperties +// - InsertRestrictions/NonInsertableNavigationProperties +// - see //TODO comments below + +// Import constants from the constants module +const { SUFFIX, TITLE_SUFFIX, SYSTEM_QUERY_OPTIONS, ODM_ANNOTATIONS, ER_ANNOTATION_PREFIX, ER_ANNOTATIONS } = constants; + +/** + * Construct an OpenAPI description from a CSDL document + * @param {object} csdl CSDL document + * @param {object} options Optional parameters + * @return {object} OpenAPI description + */ +module.exports.csdl2openapi = function ( + csdl, + { + url: serviceRoot, + servers: serversObject, + odataVersion: odataVersion, + scheme: scheme = 'https', + host: host = 'localhost', + basePath: basePath = '/service-root', + diagram: diagram = false, + maxLevels: maxLevels = 5 + } = {} +) { + // as preProcess below mutates the csdl, copy it before, to avoid side-effects on the caller side + csdl = JSON.parse(JSON.stringify(csdl)) + csdl.$Version = odataVersion ? odataVersion : '4.01' + serviceRoot = serviceRoot || (scheme + '://' + host + basePath); + const queryOptionPrefix = csdl.$Version <= '4.01' ? '$' : ''; + const typesToInline = {}; // filled in schema() and used in inlineTypes() + const boundOverloads = {}; + const derivedTypes = {}; + const alias = {}; + const namespace = { 'Edm': 'Edm' }; + const namespaceUrl = {}; + const voc = {}; + const requiredSchemas = { list: [], used: {} }; + + preProcess(csdl, boundOverloads, derivedTypes, alias, namespace, namespaceUrl, voc); + + const entityContainer = csdl.$EntityContainer ? modelElement(csdl.$EntityContainer) : {}; + if (csdl.$EntityContainer) { + let serviceName = nameParts(csdl.$EntityContainer).qualifier; + Object.keys(entityContainer).forEach(element => { + if (entityContainer[element].$Type) { + let type = nameParts(entityContainer[element].$Type).name; + if ((csdl[serviceName]?.[type]?.['@cds.autoexpose'] || csdl[serviceName]?.[type]?.['@cds.autoexposed']) && !entityContainer[type]) + entityContainer[element]['$cds.autoexpose'] = true; + } + }); + } + + const keyAsSegment = entityContainer ? entityContainer[voc.Capabilities.KeyAsSegmentSupported] : {}; + + const openapi = { + openapi: '3.0.2', + info: getInfo(csdl, entityContainer), + 'x-sap-api-type': 'ODATAV4', + 'x-odata-version': csdl.$Version, + 'x-sap-shortText': getShortText(csdl, entityContainer), + servers: getServers(serviceRoot, serversObject), + tags: entityContainer ? getTags(entityContainer) : {}, + paths: entityContainer ? getPaths(entityContainer) : {}, + components: getComponents(csdl, entityContainer) + }; + + const externalDocs = getExternalDoc(csdl); + if (externalDocs && Object.keys(externalDocs).length > 0) { + openapi.externalDocs = externalDocs; + } + const extensions = getExtensions(csdl, 'root'); + if (extensions && Object.keys(extensions).length > 0) { + Object.assign(openapi, extensions); + } + + // function to read @OpenAPI.Extensions and get them in the generated openAPI document + function getExtensions(csdl, level) { + let extensionObj = {}; + let containerSchema = {}; + if (level ==='root'){ + const namespace = csdl.$EntityContainer ? nameParts(csdl.$EntityContainer).qualifier : null; + containerSchema = csdl.$EntityContainer ? csdl[namespace] : {}; + } + else if(level === 'schema' || level === 'operation'){ + containerSchema = csdl; + } + + for (const [key, value] of Object.entries(containerSchema)) { + if (key.startsWith('@OpenAPI.Extensions')) { + const annotationProperties = key.split('@OpenAPI.Extensions.')[1]; + const keys = annotationProperties.split('.'); + if (!keys[0].startsWith("x-sap-")) { + keys[0] = (keys[0].startsWith("sap-") ? "x-" : "x-sap-") + keys[0]; + } + if (keys.length === 1) { + extensionObj[keys[0]] = value; + } else { + nestedAnnotation(extensionObj, keys[0], keys, value); + } + } + } + let extensionEnums = { + "x-sap-compliance-level": {allowedValues: ["sap:base:v1", "sap:core:v1", "sap:core:v2" ] } , + "x-sap-api-type": {allowedValues: [ "ODATA", "ODATAV4", "REST" , "SOAP"] }, + "x-sap-direction": {allowedValues: ["inbound", "outbound", "mixed"] , default : "inbound" }, + "x-sap-dpp-entity-semantics": {allowedValues: ["sap:DataSubject", "sap:DataSubjectDetails", "sap:Other"] }, + "x-sap-dpp-field-semantics": {allowedValues: ["sap:DataSubjectID", "sap:ConsentID", "sap:PurposeID", "sap:ContractRelatedID", "sap:LegalEntityID", "sap:DataControllerID", "sap:UserID", "sap:EndOfBusinessDate", "sap:BlockingDate", "sap:EndOfRetentionDate"] }, + }; + checkForExtentionEnums(extensionObj, extensionEnums); + + let extenstionSchema = { + "x-sap-stateInfo": ['state', 'deprecationDate', 'decomissionedDate', 'link'], + "x-sap-ext-overview": ['name', 'values'], + "x-sap-deprecated-operation" : ['deprecationDate', 'successorOperationRef', "successorOperationId"], + "x-sap-odm-semantic-key" : ['name', 'values'], + }; + + checkForExtentionSchema(extensionObj, extenstionSchema); + return extensionObj; + } + + function checkForExtentionEnums(extensionObj, extensionEnums){ + for (const [key, value] of Object.entries(extensionObj)) { + if(extensionEnums[key] && extensionEnums[key].allowedValues && !extensionEnums[key].allowedValues.includes(value)){ + if(extensionEnums[key].default){ + extensionObj[key] = extensionEnums[key].default; + } + else{ + delete extensionObj[key]; + } + } + } + } + + function checkForExtentionSchema(extensionObj, extenstionSchema) { + for (const [key, value] of Object.entries(extensionObj)) { + if (extenstionSchema[key]) { + if (Array.isArray(value)) { + extensionObj[key] = value.filter((v) => extenstionSchema[key].includes(v)); + } else if (typeof value === "object" && value !== null) { + for (const field in value) { + if (!extenstionSchema[key].includes(field)) { + delete extensionObj[key][field]; + } + } + } + } + } + } + + + function nestedAnnotation(resObj, openapiProperty, keys, value) { + if (resObj[openapiProperty] === undefined) { + resObj[openapiProperty] = {}; + } + + let node = resObj[openapiProperty]; + + // traverse the annotation property and define the objects if they're not defined + for (let nestedIndex = 1; nestedIndex < keys.length - 1; nestedIndex++) { + const nestedElement = keys[nestedIndex]; + if (node[nestedElement] === undefined) { + node[nestedElement] = {}; + } + node = node[nestedElement]; + } + + // set value annotation property + node[keys[keys.length - 1]] = value; + } + + if (!csdl.$EntityContainer) { + delete openapi.servers; + delete openapi.tags; + } + + security(openapi, entityContainer); + + return openapi; + + + /** + * Collect model info for easier lookup + * @param {object} csdl CSDL document + * @param {object} boundOverloads Map of action/function names to bound overloads + * @param {object} derivedTypes Map of type names to derived types + * @param {object} alias Map of namespace or alias to alias + * @param {object} namespace Map of namespace or alias to namespace + * @param {object} namespaceUrl Map of namespace to reference URL + * @param {object} voc Map of vocabularies and terms + */ + function preProcess(csdl, boundOverloads, derivedTypes, alias, namespace, namespaceUrl, voc) { + Object.keys(csdl.$Reference || {}).forEach(url => { + const reference = csdl.$Reference[url]; + (reference.$Include || []).forEach(include => { + const qualifier = include.$Alias || include.$Namespace; + alias[include.$Namespace] = qualifier; + namespace[qualifier] = include.$Namespace; + namespace[include.$Namespace] = include.$Namespace; + namespaceUrl[include.$Namespace] = url; + }); + }); + + getVocabularies(voc, alias); + + Object.keys(csdl).filter(name => isIdentifier(name)).forEach(name => { + const schema = csdl[name]; + const qualifier = schema.$Alias || name; + const isDefaultNamespace = schema[voc.Core.DefaultNamespace]; + + alias[name] = qualifier; + namespace[qualifier] = name; + namespace[name] = name; + + Object.keys(schema).filter(iName => isIdentifier(iName)).forEach(iName2 => { + const qualifiedName = qualifier + '.' + iName2; + const element = schema[iName2]; + if (Array.isArray(element)) { + element.filter(overload => overload.$IsBound).forEach(overload => { + const type = overload.$Parameter[0].$Type + (overload.$Parameter[0].$Collection ? '-c' : ''); + if (!boundOverloads[type]) boundOverloads[type] = []; + boundOverloads[type].push({ name: (isDefaultNamespace ? iName2 : qualifiedName), overload: overload }); + }); + } else if (element.$BaseType) { + const base = namespaceQualifiedName(element.$BaseType); + if (!derivedTypes[base]) derivedTypes[base] = []; + derivedTypes[base].push(qualifiedName); + } + }); + + Object.keys(schema.$Annotations || {}).forEach(target => { + const annotations = schema.$Annotations[target]; + const segments = target.split('/'); + const open = segments[0].indexOf('('); + let element; + if (open == -1) { + element = modelElement(segments[0]); + } else { + element = modelElement(segments[0].substring(0, open)); + let args = segments[0].substring(open + 1, segments[0].length - 1); + element = element.find( + (overload) => + (overload.$Kind == "Action" && + overload.$IsBound != true && + args == "") || + (overload.$Kind == "Action" && + args == + (overload.$Parameter[0].$Collection + ? `Collection(${overload.$Parameter[0].$Type})` + : overload.$Parameter[0].$Type || "")) || + (overload.$Parameter || []) + .map((p) => { + const type = p.$Type || "Edm.String"; + return p.$Collection ? `Collection(${type})` : type; + }) + .join(",") == args + ); + } + if (!element) { + DEBUG?.(`Invalid annotation target '${target}'`); + } else if (Array.isArray(element)) { + //TODO: action or function: + //- loop over all overloads + //- if there are more segments, a parameter or the return type is targeted + } else { + switch (segments.length) { + case 1: + Object.assign(element, annotations); + break; + case 2: + if (['Action', 'Function'].includes(element.$Kind)) { + if (segments[1] == '$ReturnType') { + if (element.$ReturnType) + Object.assign(element.$ReturnType, annotations); + } else { + const parameter = element.$Parameter.find(p => p.$Name == segments[1]); + Object.assign(parameter, annotations); + } + } else { + if (element[segments[1]]) { + Object.assign(element[segments[1]], annotations); + } else { + // DEBUG?.(`Invalid annotation target '${target}'`) + } + } + break; + default: + DEBUG?.('More than two annotation target path segments'); + } + } + }); + }); + } + + /** + * Construct map of qualified term names + * @param {object} voc Map of vocabularies and terms + * @param {object} alias Map of namespace or alias to alias + */ + function getVocabularies(voc, alias) { + const terms = { + Authorization: ['Authorizations', 'SecuritySchemes'], + Capabilities: ['BatchSupport', 'BatchSupported', 'ChangeTracking', 'CountRestrictions', 'DeleteRestrictions', 'DeepUpdateSupport', 'ExpandRestrictions', + 'FilterRestrictions', 'IndexableByKey', 'InsertRestrictions', 'KeyAsSegmentSupported', 'NavigationRestrictions', 'OperationRestrictions', + 'ReadRestrictions', 'SearchRestrictions', 'SelectSupport', 'SkipSupported', 'SortRestrictions', 'TopSupported', 'UpdateRestrictions'], + Core: ['AcceptableMediaTypes', 'Computed', 'ComputedDefaultValue', 'DefaultNamespace', 'Description', 'Example', 'Immutable', 'LongDescription', + 'OptionalParameter', 'Permissions', 'SchemaVersion'], + JSON: ['Schema'], + Validation: ['AllowedValues', 'Exclusive', 'Maximum', 'Minimum', 'Pattern'] + }; + + Object.keys(terms).forEach(vocab => { + voc[vocab] = {}; + terms[vocab].forEach(term => { + if (alias['Org.OData.' + vocab + '.V1'] != undefined) + voc[vocab][term] = '@' + alias['Org.OData.' + vocab + '.V1'] + '.' + term; + }); + }); + + voc.Common = { + Label: `@${alias['com.sap.vocabularies.Common.v1']}.Label` + } + } + + /** + * Construct the Info Object + * @param {object} csdl CSDL document + * @param {object} entityContainer Entity Container object + * @return {object} Info Object + */ + function getInfo(csdl, entityContainer) { + const namespace = csdl.$EntityContainer ? nameParts(csdl.$EntityContainer).qualifier : null; + const containerSchema = csdl.$EntityContainer ? csdl[namespace] : {}; + let description; + if (entityContainer && entityContainer[voc.Core.LongDescription]) { + description = entityContainer[voc.Core.LongDescription]; + } + else if (containerSchema && containerSchema[voc.Core.LongDescription]) { + description = containerSchema[voc.Core.LongDescription]; + } + else { + description = "Use @Core.LongDescription: '...' on your CDS service to provide a meaningful description."; + } + description += (diagram ? getResourceDiagram(csdl, entityContainer) : ''); + let title; + if (entityContainer && entityContainer[voc.Common.Label]) { + title = entityContainer[voc.Common.Label]; + } + else { + title = "Use @title: '...' on your CDS service to provide a meaningful title."; + } + return { + title: title, + description: csdl.$EntityContainer ? description : '', + version: containerSchema[voc.Core.SchemaVersion] || '' + }; + } + + /** + * Construct the externalDocs Object + * @param {object} csdl CSDL document + * @return {object} externalDocs Object + */ + function getExternalDoc(csdl) { + const namespace = csdl.$EntityContainer ? nameParts(csdl.$EntityContainer).qualifier : null; + const containerSchema = csdl.$EntityContainer ? csdl[namespace] : {}; + let externalDocs = {}; + if (containerSchema?.['@OpenAPI.externalDocs.description']) { + externalDocs.description = containerSchema['@OpenAPI.externalDocs.description']; + } + if (containerSchema?.['@OpenAPI.externalDocs.url']) { + externalDocs.url = containerSchema['@OpenAPI.externalDocs.url']; + } + return externalDocs; + } + + /** + * Construct resource diagram using web service at https://yuml.me + * @param {object} csdl CSDL document + * @param {object} entityContainer Entity Container object + * @return {string} resource diagram + */ + function getResourceDiagram(csdl, entityContainer) { + let diagram = ''; + let comma = ''; + //TODO: make colors configurable + let color = { resource: '{bg:lawngreen}', entityType: '{bg:lightslategray}', complexType: '', external: '{bg:whitesmoke}' } + + Object.keys(csdl).filter(name => isIdentifier(name)).forEach(namespace => { + const schema = csdl[namespace]; + Object.keys(schema).filter(name => isIdentifier(name) && ['EntityType', 'ComplexType'].includes(schema[name].$Kind)) + .forEach(typeName => { + const type = schema[typeName]; + diagram += comma + + (type.$BaseType ? '[' + nameParts(type.$BaseType).name + ']^' : '') + + '[' + typeName + (type.$Kind == 'EntityType' ? color.entityType : color.complexType) + ']'; + Object.keys(type).filter(name => isIdentifier(name)).forEach(propertyName => { + const property = type[propertyName]; + const targetNP = nameParts(property.$Type || 'Edm.String'); + if (property.$Kind == 'NavigationProperty' || targetNP.qualifier != 'Edm') { + const target = modelElement(property.$Type); + const bidirectional = property.$Partner && target && target[property.$Partner] && target[property.$Partner].$Partner == propertyName; + // Note: if the partner has the same name then it will also be depicted + if (!bidirectional || propertyName <= property.$Partner) { + diagram += ',[' + typeName + ']' + + ((property.$Kind != 'NavigationProperty' || property.$ContainsTarget) ? '++' : (bidirectional ? cardinality(target[property.$Partner]) : '')) + + '-' + + cardinality(property) + + ((property.$Kind != 'NavigationProperty' || bidirectional) ? '' : '>') + + '[' + + (target ? targetNP.name : property.$Type + color.external) + + ']'; + } + } + }); + comma = ','; + }); + }); + + Object.keys(entityContainer).filter(name => isIdentifier(name)).reverse().forEach(name => { + const resource = entityContainer[name]; + if (resource.$Type) { + diagram += comma + + '[' + name + '%20' + color.resource + ']' // additional space in case entity set and type have same name + + '++-' + + cardinality(resource) + + '>[' + nameParts(resource.$Type).name + ']'; + } else { + if (resource.$Action) { + diagram += comma + + '[' + name + color.resource + ']'; + const overload = modelElement(resource.$Action).find(pOverload => !pOverload.$IsBound); + diagram += overloadDiagram(name, overload); + } else if (resource.$Function) { + diagram += comma + + '[' + name + color.resource + ']'; + const overloads = modelElement(resource.$Function); + if (overloads) { + const unbound = overloads.filter(overload => !overload.$IsBound); + // TODO: loop over all overloads, add new source box after first arrow + diagram += overloadDiagram(name, unbound[0]); + } + } + } + }); + + if (diagram != '') { + diagram = '\n\n## Entity Data Model\n![ER Diagram](https://yuml.me/diagram/class/' + + diagram + + ')\n\n### Legend\n![Legend](https://yuml.me/diagram/plain;dir:TB;scale:60/class/[External.Type' + color.external + + '],[ComplexType' + color.complexType + '],[EntityType' + color.entityType + + '],[EntitySet/Singleton/Operation' + color.resource + '])'; + } + + return diagram; + + /** + * Diagram representation of property cardinality + * @param {object} typedElement Typed model element, e.g. property + * @return {string} cardinality + */ + function cardinality(typedElement) { + return typedElement.$Collection ? '*' : (typedElement.$Nullable ? '0..1' : ''); + } + + /** + * Diagram representation of action or function overload + * @param {string} name Name of action or function import + * @param {object} overload Action or function overload + * @return {string} diagram part + */ + function overloadDiagram(name, overload) { + let diag = ""; + if (overload.$ReturnType) { + const type = modelElement(overload.$ReturnType.$Type || "Edm.String"); + if (type) { + diag += "-" + cardinality(overload.$ReturnType) + ">[" + nameParts(overload.$ReturnType.$Type).name + "]"; + } + } + for (const param of overload.$Parameter || []) { + const type = modelElement(param.$Type || "Edm.String"); + if (type) { + diag += comma + "[" + name + color.resource + "]in-" + cardinality(param.$Type) + ">[" + nameParts(param.$Type).name + "]"; + } + } + return diag; + } + } + + /** + * Find model element by qualified name + * @param {string} qname Qualified name of model element + * @return {object} Model element + */ + function modelElement(qname) { + const q = nameParts(qname); + const schema = csdl[q.qualifier] || csdl[namespace[q.qualifier]]; + return schema ? schema[q.name] : null; + } + + /** + * Construct the short text + * @param {object} csdl CSDL document + * @param {object} entityContainer Entity Container object + * @return {string} short text + */ + function getShortText(csdl, entityContainer) { + const namespace = csdl.$EntityContainer ? nameParts(csdl.$EntityContainer).qualifier : null; + const containerSchema = csdl.$EntityContainer ? csdl[namespace] : {}; + let shortText; + if (entityContainer && entityContainer[voc.Core.Description]) { + shortText = entityContainer[voc.Core.Description]; + } + else if (containerSchema && containerSchema[voc.Core.Description]) { + shortText = containerSchema[voc.Core.Description]; + } + else { + shortText = "Use @Core.Description: '...' on your CDS service to provide a meaningful short text."; + } + return shortText; + } + + /** + * Construct an array of Server Objects + * @param {object} serviceRoot The service root + * @param {object} serversObject Input servers object + * @return {Array} The list of servers + */ + function getServers(serviceRoot, serversObject) { + let servers; + if (serversObject) { + try { + servers = JSON.parse(serversObject); + } catch (err) { + throw new Error(`The input server object is invalid.`); + } + + if (!servers.length) { + throw new Error(`The input server object should be an array.`); + } + } else { + servers = [{ url: serviceRoot }]; + } + return servers; + } + + /** + * Construct an array of Tag Objects from the entity container + * @param {object} container The entity container + * @return {Array} The list of tags + */ + function getTags(container) { + const tags = new Map(); + // all entity sets and singletons + Object.keys(container) + .filter(name => isIdentifier(name) && container[name].$Type) + .forEach(child => { + const type = modelElement(container[child].$Type) || {}; + const tag = { + name: type[voc.Common.Label] || child + }; + const description = container[child][voc.Core.Description] || type[voc.Core.Description]; + if (description) tag.description = description; + tags.set(tag.name, tag); + }); + return Array.from(tags.values()).sort((pre, next) => pre.name.localeCompare(next.name)); + } + + /** + * Construct the Paths Object from the entity container + * @param {object} container Entity container + * @return {object} Paths Object + */ + function getPaths(container) { + const paths = {}; + const resources = Object.keys(container).filter(name => isIdentifier(name)); + resources.forEach(name => { + let child = container[name]; + if (child.$Type) { + const type = modelElement(child.$Type); + const sourceName = (type && type[voc.Common.Label]) || name; + // entity sets and singletons are almost containment navigation properties + child.$ContainsTarget = true; + pathItems(paths, '/' + name, [], child, child, sourceName, sourceName, child, 0, ''); + } else if (child.$Action) { + pathItemActionImport(paths, name, child); + } else if (child.$Function) { + pathItemFunctionImport(paths, name, child); + } else { + DEBUG?.('Unrecognized entity container child: ' + name); + } + }) + if (resources.length > 0) pathItemBatch(paths, container); + return Object.keys(paths).sort().reduce((p, c) => (p[c] = paths[c], p), {}); + } + + /** + * Add path and Path Item Object for a navigation segment + * @param {object} paths Paths Object to augment + * @param {string} prefix Prefix for path + * @param {Array} prefixParameters Parameter Objects for prefix + * @param {object} element Model element of navigation segment + * @param {object} root Root model element + * @param {string} sourceName Name of path source + * @param {string} targetName Name of path target + * @param {string} target Target container child of path + * @param {integer} level Number of navigation segments so far + * @param {string} navigationPath Path for finding navigation restrictions + */ + function pathItems(paths, prefix, prefixParameters, element, root, sourceName, targetName, target, level, navigationPath) { + const name = prefix.substring(prefix.lastIndexOf('/') + 1); + const type = modelElement(element.$Type); + const pathItem = {}; + const restrictions = navigationPropertyRestrictions(root, navigationPath); + const nonExpandable = nonExpandableProperties(root, navigationPath); + + paths[prefix] = pathItem; + if (prefixParameters.length > 0) pathItem.parameters = prefixParameters; + + operationRead(pathItem, element, name, sourceName, targetName, target, level, restrictions, false, nonExpandable); + if (!root['$cds.autoexpose'] && element.$Collection && (element.$ContainsTarget || level < 2 && target)) { + operationCreate(pathItem, element, name, sourceName, targetName, target, level, restrictions); + } + pathItemsForBoundOperations(paths, prefix, prefixParameters, element, sourceName); + + if (element.$ContainsTarget) { + if (element.$Collection) { + if (level < maxLevels) + pathItemsWithKey(paths, prefix, prefixParameters, element, root, sourceName, targetName, target, level, navigationPath, restrictions, nonExpandable); + } else { + if (!root['$cds.autoexpose']) { + operationUpdate(pathItem, element, name, sourceName, target, level, restrictions); + if (element.$Nullable) { + operationDelete(pathItem, element, name, sourceName, target, level, restrictions); + } + } + pathItemsForBoundOperations(paths, prefix, prefixParameters, element, sourceName); + pathItemsWithNavigation(paths, prefix, prefixParameters, type, root, sourceName, level, navigationPath); + } + } + + if (Object.keys(pathItem).filter((i) => i !== "parameters").length === 0) + delete paths[prefix]; + } + + /** + * Find navigation restrictions for a navigation path + * @param {object} root Root model element + * @param {string} navigationPath Path for finding navigation restrictions + * @return Navigation property restrictions of navigation segment + */ + function navigationPropertyRestrictions(root, navigationPath) { + const navigationRestrictions = root[voc.Capabilities.NavigationRestrictions] || {}; + return (navigationRestrictions.RestrictedProperties || []).find(item => navigationPropertyPath(item.NavigationProperty) == navigationPath) + || {}; + } + + /** + * Find non-expandable properties for a navigation path + * @param {object} root Root model element + * @param {string} navigationPath Path for finding navigation restrictions + * @return Navigation property restrictions of navigation segment + */ + function nonExpandableProperties(root, navigationPath) { + const expandRestrictions = root[voc.Capabilities.ExpandRestrictions] || {}; + const prefix = navigationPath.length === 0 ? '' : navigationPath + '/' + const from = prefix.length + const nonExpandable = [] + for (const path of (expandRestrictions.NonExpandableProperties || [])) { + if (path.startsWith(prefix)) { + nonExpandable.push(path.substring(from)) + } + } + return nonExpandable; + } + + /** + * Add path and Path Item Object for a navigation segment with key + * @param {object} paths Paths Object to augment + * @param {string} prefix Prefix for path + * @param {Array} prefixParameters Parameter Objects for prefix + * @param {object} element Model element of navigation segment + * @param {object} root Root model element + * @param {string} sourceName Name of path source + * @param {string} targetName Name of path target + * @param {string} target Target container child of path + * @param {integer} level Number of navigation segments so far + * @param {string} navigationPath Path for finding navigation restrictions + * @param {object} restrictions Navigation property restrictions of navigation segment + * @param {array} nonExpandable Non-expandable navigation properties + */ + function pathItemsWithKey(paths, prefix, prefixParameters, element, root, sourceName, targetName, target, level, navigationPath, restrictions, nonExpandable) { + const targetIndexable = target == null || target[voc.Capabilities.IndexableByKey] != false; + if (restrictions.IndexableByKey == true || restrictions.IndexableByKey != false && targetIndexable) { + const name = prefix.substring(prefix.lastIndexOf('/') + 1); + const type = modelElement(element.$Type); + const key = entityKey(type, level); + if (key.parameters.length > 0) { + const path = prefix + key.segment; + const parameters = prefixParameters.concat(key.parameters); + const pathItem = { parameters: parameters }; + paths[path] = pathItem; + + operationRead(pathItem, element, name, sourceName, targetName, target, level, restrictions, true, nonExpandable); + if (!root['$cds.autoexpose']) { + operationUpdate(pathItem, element, name, sourceName, target, level, restrictions, true); + operationDelete(pathItem, element, name, sourceName, target, level, restrictions, true); + } + if (Object.keys(pathItem).filter((i) => i !== "parameters").length === 0) + delete paths[path]; + + pathItemsForBoundOperations(paths, path, parameters, element, sourceName, true); + pathItemsWithNavigation(paths, path, parameters, type, root, sourceName, level, navigationPath); + } + } + } + + /** + * Construct Operation Object for create + * @param {object} pathItem Path Item Object to augment + * @param {object} element Model element of navigation segment + * @param {string} name Name of navigation segment + * @param {string} sourceName Name of path source + * @param {string} targetName Name of path target + * @param {string} target Target container child of path + * @param {integer} level Number of navigation segments so far + * @param {object} restrictions Navigation property restrictions of navigation segment + */ + function operationCreate(pathItem, element, name, sourceName, targetName, target, level, restrictions) { + const insertRestrictions = restrictions.InsertRestrictions || target && target[voc.Capabilities.InsertRestrictions] || {}; + let countRestrictions = target && (target[voc.Capabilities.CountRestrictions]?.Countable === false); // count property will be added if CountRestrictions is false + if (insertRestrictions.Insertable !== false) { + const lname = pluralize.singular(splitName(name)); + const type = modelElement(element.$Type); + pathItem.post = { + summary: insertRestrictions.Description || operationSummary('Creates', name, sourceName, level, true, true), + tags: [sourceName], + requestBody: { + description: type && type[voc.Core.Description] || 'New ' + lname, + required: true, + content: { + 'application/json': { + schema: ref(element.$Type, SUFFIX.create), + } + } + }, + responses: response(201, 'Created ' + lname, { $Type: element.$Type }, insertRestrictions.ErrorResponses, !countRestrictions), + }; + if (insertRestrictions.LongDescription) pathItem.post.description = insertRestrictions.LongDescription; + if (targetName && sourceName != targetName) pathItem.post.tags.push(targetName); + customParameters(pathItem.post, insertRestrictions); + } + } + + /** + * Split camel-cased name into words + * @param {string} name Name to split + * @return {string} Split name + */ + function splitName(name) { + return name.split(/(?=[A-Z])/g).join(' ').toLowerCase().replace(/ i d/g, ' id'); + } + + /** + * Construct operation summary + * @param {string} operation Operation (verb) + * @param {string} name Name of navigation segment + * @param {string} sourceName Name of path source + * @param {integer} level Number of navigation segments so far + * @param {boolean} collection Access a collection + * @param {boolean} byKey Access by key + * @return {string} Operation Text + */ + function operationSummary(operation, name, sourceName, level, collection, byKey) { + let lname = splitName(name); + let sname = splitName(sourceName); + + return operation + ' ' + + (byKey ? 'a single ' : (collection ? 'a list of ' : '')) + + (byKey ? pluralize.singular(lname) : lname) + //TODO: suppress "a" for all singletons + + (level == 0 ? '' : (level == 1 && sname == 'me' ? ' of me' : ' of a ' + pluralize.singular(sname))) + + '.' + } + + /** + * Construct Operation Object for read + * @param {object} pathItem Path Item Object to augment + * @param {object} element Model element of navigation segment + * @param {string} name Name of navigation segment + * @param {string} sourceName Name of path source + * @param {string} targetName Name of path target + * @param {string} target Target container child of path + * @param {integer} level Number of navigation segments so far + * @param {object} restrictions Navigation property restrictions of navigation segment + * @param {boolean} byKey Read by key + * @param {array} nonExpandable Non-expandable navigation properties + */ + function operationRead(pathItem, element, name, sourceName, targetName, target, level, restrictions, byKey, nonExpandable) { + const targetRestrictions = target?.[voc.Capabilities.ReadRestrictions]; + const readRestrictions = restrictions.ReadRestrictions || targetRestrictions || {}; + const readByKeyRestrictions = readRestrictions.ReadByKeyRestrictions; + let readable = true; + let countRestrictions = target && (target[voc.Capabilities.CountRestrictions]?.Countable === false); + if (byKey && readByKeyRestrictions && readByKeyRestrictions.Readable !== undefined) + readable = readByKeyRestrictions.Readable; + else if (readRestrictions.Readable !== undefined) + readable = readRestrictions.Readable; + + if (readable) { + let descriptions = (level == 0 ? targetRestrictions : restrictions.ReadRestrictions) || {}; + if (byKey) descriptions = descriptions.ReadByKeyRestrictions || {}; + const lname = splitName(name); + const collection = !byKey && element.$Collection; + const operation = { + summary: descriptions.Description || operationSummary('Retrieves', name, sourceName, level, element.$Collection, byKey), + tags: [sourceName], + parameters: [], + responses: response(200, 'Retrieved ' + (byKey ? pluralize.singular(lname) : lname), { $Type: element.$Type, $Collection: collection }, + byKey ? readByKeyRestrictions?.ErrorResponses : readRestrictions?.ErrorResponses, !countRestrictions) + }; + const deltaSupported = element[voc.Capabilities.ChangeTracking] && element[voc.Capabilities.ChangeTracking].Supported; + if (!byKey && deltaSupported) { + operation.responses[200].content['application/json'].schema.properties['@odata.deltaLink'] = { + type: 'string', + example: basePath + '/' + name + '?$deltatoken=opaque server-generated token for fetching the delta' + } + } + if (descriptions.LongDescription) operation.description = descriptions.LongDescription; + if (target && sourceName != targetName) operation.tags.push(targetName); + customParameters(operation, byKey ? readByKeyRestrictions || readRestrictions : readRestrictions); + + if (collection) { + optionTop(operation.parameters, target, restrictions); + optionSkip(operation.parameters, target, restrictions); + if (csdl.$Version >= '4.0') optionSearch(operation.parameters, target, restrictions); + optionFilter(operation.parameters, target, restrictions); + optionCount(operation.parameters, target); + optionOrderBy(operation.parameters, element, target, restrictions); + } + + optionSelect(operation.parameters, element, target, restrictions); + optionExpand(operation.parameters, element, target, nonExpandable); + + pathItem.get = operation; + } + } + + /** + * Add custom headers and query options + * @param {object} operation Operation object to augment + * @param {object} restrictions Restrictions for operation + */ + function customParameters(operation, restrictions) { + if ( + !operation.parameters && + (restrictions.CustomHeaders || restrictions.CustomQueryOptions) + ) + operation.parameters = []; + for (const custom of restrictions.CustomHeaders || []) { + operation.parameters.push(customParameter(custom, "header")); + } + + for (const custom of restrictions.CustomQueryOptions || []) { + operation.parameters.push(customParameter(custom, "query")); + } + } + + /** + * Construct custom parameter + * @param {object} custom custom parameter in OData format + * @param {string} location "header" or "query" + */ + function customParameter(custom, location) { + return { + name: custom.Name, + in: location, + required: custom.Required || false, + ...(custom.Description && { description: custom.Description }), + schema: { + type: "string", + ...(custom.DocumentationURL && { + externalDocs: { url: custom.DocumentationURL }, + }), + //TODO: Examples + }, + }; + } + + /** + * Add parameter for query option $count + * @param {Array} parameters Array of parameters to augment + * @param {string} target Target container child of path + */ + function optionCount(parameters, target) { + const targetRestrictions = target && target[voc.Capabilities.CountRestrictions]; + const targetCountable = target == null + || targetRestrictions == null + || targetRestrictions.Countable !== false; + + if (targetCountable) { + parameters.push({ + + $ref: '#/components/parameters/count' + }); + } + } + + /** + * Add parameter for query option $expand + * @param {Array} parameters Array of parameters to augment + * @param {object} element Model element of navigation segment + * @param {string} target Target container child of path + * @param {array} nonExpandable Non-expandable navigation properties + */ + function optionExpand(parameters, element, target, nonExpandable) { + const targetRestrictions = target && target[voc.Capabilities.ExpandRestrictions]; + const supported = targetRestrictions == null || targetRestrictions.Expandable != false; + if (supported) { + const expandItems = ['*'].concat(navigationPaths(element).filter(path => !nonExpandable.includes(path))); + if (expandItems.length > 1) { + parameters.push({ + name: queryOptionPrefix + 'expand', + description: (targetRestrictions && targetRestrictions[voc.Core.Description]) + || 'The value of $expand query option is a comma-separated list of navigation property names, \ +stream property names, or $value indicating the stream content of a media-entity. \ +The corresponding related entities and stream values will be represented inline, \ +see [Expand](http://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part1-protocol.html#sec_SystemQueryOptionexpand)', + in: 'query', + explode: false, + schema: { + type: 'array', + uniqueItems: true, + items: { + type: 'string', + enum: expandItems + } + } + }); + } + } + } + + /** + * Collect navigation paths of a navigation segment and its potentially structured components + * @param {object} element Model element of navigation segment + * @param {string} prefix Navigation prefix + * @param {integer} level Number of navigation segments so far + * @return {Array} Array of navigation property paths + */ + function navigationPaths(element, prefix = '', level = 0) { + const paths = []; + const type = modelElement(element.$Type); + const properties = propertiesOfStructuredType(type); + Object.keys(properties).forEach(key => { + if (properties[key].$Kind == 'NavigationProperty') { + paths.push(prefix + key) + } else if (properties[key].$Type && level < maxLevels) { + paths.push(...navigationPaths(properties[key], prefix + key + '/', level + 1)); + } + }) + return paths; + } + + /** + * Add parameter for query option $filter + * @param {Array} parameters Array of parameters to augment + * @param {string} target Target container child of path + * @param {object} restrictions Navigation property restrictions of navigation segment + */ + function optionFilter(parameters, target, restrictions) { + const filterRestrictions = restrictions.FilterRestrictions || target && target[voc.Capabilities.FilterRestrictions] || {}; + + if (filterRestrictions.Filterable !== false) { + const filter = { + name: queryOptionPrefix + 'filter', + description: filterRestrictions[voc.Core.Description] + || 'Filter items by property values, see [Filtering](http://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part1-protocol.html#sec_SystemQueryOptionfilter)', + in: 'query', + schema: { + type: 'string' + } + }; + if (filterRestrictions.RequiresFilter) + filter.required = true; + if (filterRestrictions.RequiredProperties) { + filter.description += '\n\nRequired filter properties:'; + filterRestrictions.RequiredProperties.forEach( + item => filter.description += '\n- ' + propertyPath(item) + ); + } + parameters.push(filter); + } + } + + /** + * Add parameter for query option $orderby + * @param {Array} parameters Array of parameters to augment + * @param {object} element Model element of navigation segment + * @param {string} target Target container child of path + * @param {object} restrictions Navigation property restrictions of navigation segment + */ + function optionOrderBy(parameters, element, target, restrictions) { + const sortRestrictions = restrictions.SortRestrictions || target && target[voc.Capabilities.SortRestrictions] || {}; + + if (sortRestrictions.Sortable !== false) { + const nonSortable = {}; + (sortRestrictions.NonSortableProperties || []).forEach(name => { + nonSortable[propertyPath(name)] = true; + }); + const orderbyItems = []; + primitivePaths(element).filter(property => !nonSortable[property]).forEach(property => { + orderbyItems.push(property); + orderbyItems.push(property + ' desc'); + }); + if (orderbyItems.length > 0) { + parameters.push({ + name: queryOptionPrefix + 'orderby', + description: sortRestrictions[voc.Core.Description] + || 'Order items by property values, see [Sorting](http://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part1-protocol.html#sec_SystemQueryOptionorderby)', + in: 'query', + explode: false, + schema: { + type: 'array', + uniqueItems: true, + items: { + type: 'string', + enum: orderbyItems + } + } + }); + } + } + } + + /** + * Unpack EnumMember value if it uses CSDL JSON CS01 style, like CAP does + * @param {string or object} path Qualified name of referenced type + * @return {object} Reference Object + */ + function enumMember(member) { + if (typeof member == 'string') + return member; + else if (typeof member == 'object') + return member.$EnumMember; + } + + /** + * Unpack NavigationPropertyPath value if it uses CSDL JSON CS01 style, like CAP does + * @param {string or object} path Qualified name of referenced type + * @return {object} Reference Object + */ + function navigationPropertyPath(path) { + if (typeof path == 'string') + return path; + else + return path.$NavigationPropertyPath; + } + + /** + * Unpack PropertyPath value if it uses CSDL JSON CS01 style, like CAP does + * @param {string or object} path Qualified name of referenced type + * @return {object} Reference Object + */ + function propertyPath(path) { + if (typeof path == 'string') + return path; + else + return path.$PropertyPath; + } + + /** + * Collect primitive paths of a navigation segment and its potentially structured components + * @param {object} element Model element of navigation segment + * @param {string} prefix Navigation prefix + * @return {Array} Array of primitive property paths + */ + function primitivePaths(element, prefix = '') { + const paths = []; + const elementType = modelElement(element.$Type); + + if (!elementType) { + DEBUG?.(`Unknown type for element: ${JSON.stringify(element)}`); + return paths; + } + + const propsOfType = propertiesOfStructuredType(elementType); + const ignore = Object.entries(propsOfType) + .filter(entry => entry[1].$Kind !== 'NavigationProperty') + .filter(entry => entry[1].$Type) + .filter(entry => nameParts(entry[1].$Type).qualifier !== 'Edm') + .filter(entry => !modelElement(entry[1].$Type)); + + // Keep old logging + ignore.forEach(entry => DEBUG?.(`Unknown type for element: ${JSON.stringify(entry)}`)); + + const properties = Object.entries(propsOfType) + .filter(entry => entry[1].$Kind !== 'NavigationProperty') + .filter(entry => !ignore.includes(entry)) + .map(entryToProperty({ path: prefix, typeRefChain: [] })); + + for (let i = 0; i < properties.length; i++) { + const property = properties[i]; + if (!property.isComplex) { + paths.push(property.path); + continue; + } + + const typeRefChainTail = property.typeRefChain[property.typeRefChain.length - 1]; + + // Allow full cycle to be shown (0) times + if (property.typeRefChain.filter(_type => _type === typeRefChainTail).length > 1) { + DEBUG?.(`Cycle detected ${property.typeRefChain.join('->')}`); + continue; + } + + const expanded = Object.entries(property.properties) + .filter(pProperty => pProperty[1].$Kind !== 'NavigationProperty') + .map(entryToProperty(property)) + properties.splice(i + 1, 0, ...expanded); + } + + return paths; + } + + function entryToProperty(parent) { + + return function (entry) { + const key = entry[0]; + const property = entry[1]; + const propertyType = property.$Type && modelElement(property.$Type); + + if (propertyType && propertyType.$Kind && propertyType.$Kind === 'ComplexType') { + return { + properties: propertiesOfStructuredType(propertyType), + path: `${parent.path}${key}/`, + typeRefChain: parent.typeRefChain.concat(property.$Type), + isComplex: true + } + } + + return { + properties: {}, + path: `${parent.path}${key}`, + typeRefChain: [], + isComplex: false, + } + }; + } + + /** + * Add parameter for query option $search + * @param {Array} parameters Array of parameters to augment + * @param {string} target Target container child of path + * @param {object} restrictions Navigation property restrictions of navigation segment + */ + function optionSearch(parameters, target, restrictions) { + const searchRestrictions = restrictions.SearchRestrictions || target && target[voc.Capabilities.SearchRestrictions] || {}; + + if (searchRestrictions.Searchable !== false) { + if (searchRestrictions[voc.Core.Description]) { + parameters.push({ + name: queryOptionPrefix + 'search', + description: searchRestrictions[voc.Core.Description], + in: 'query', + schema: { type: 'string' } + }); + } else { + parameters.push({ $ref: '#/components/parameters/search' }); + } + } + } + + /** + * Add parameter for query option $select + * @param {Array} parameters Array of parameters to augment + * @param {object} element Model element of navigation segment + * @param {string} target Target container child of path + * @param {object} restrictions Navigation property restrictions of navigation segment + */ + function optionSelect(parameters, element, target, restrictions) { + const selectSupport = restrictions.SelectSupport || target && target[voc.Capabilities.SelectSupport] || {}; + + if (selectSupport.Supported !== false) { + const type = modelElement(element.$Type) || {}; + const properties = propertiesOfStructuredType(type); + const selectItems = []; + Object.keys(properties).filter(key => properties[key].$Kind != 'NavigationProperty').forEach( + key => selectItems.push(key) + ) + if (selectItems.length > 0) { + parameters.push({ + name: queryOptionPrefix + 'select', + description: 'Select properties to be returned, see [Select](http://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part1-protocol.html#sec_SystemQueryOptionselect)', + in: 'query', + explode: false, + schema: { + type: 'array', + uniqueItems: true, + items: { + type: 'string', + enum: selectItems + } + } + }); + } + } + } + + /** + * Add parameter for query option $skip + * @param {Array} parameters Array of parameters to augment + * @param {string} target Target container child of path + * @param {object} restrictions Navigation property restrictions of navigation segment + */ + function optionSkip(parameters, target, restrictions) { + const supported = restrictions.SkipSupported !== undefined + ? restrictions.SkipSupported + : target == null || target[voc.Capabilities.SkipSupported] !== false; + + if (supported) { + parameters.push({ + $ref: '#/components/parameters/skip' + }); + } + } + + /** + * Add parameter for query option $top + * @param {Array} parameters Array of parameters to augment + * @param {string} target Target container child of path + * @param {object} restrictions Navigation property restrictions of navigation segment + */ + function optionTop(parameters, target, restrictions) { + const supported = restrictions.TopSupported !== undefined + ? restrictions.TopSupported + : target == null || target[voc.Capabilities.TopSupported] !== false; + + if (supported) { + parameters.push({ + $ref: '#/components/parameters/top' + }); + } + } + + /** + * Construct Operation Object for update + * @param {object} pathItem Path Item Object to augment + * @param {object} element Model element of navigation segment + * @param {string} name Name of navigation segment + * @param {string} sourceName Name of path source + * @param {string} target Target container child of path + * @param {integer} level Number of navigation segments so far + * @param {object} restrictions Navigation property restrictions of navigation segment + * @param {boolean} byKey Update by key + */ + function operationUpdate(pathItem, element, name, sourceName, target, level, restrictions, byKey) { + const updateRestrictions = restrictions.UpdateRestrictions || target && target[voc.Capabilities.UpdateRestrictions] || {}; + let countRestrictions = target && (target[voc.Capabilities.CountRestrictions]?.Countable === false); + if (updateRestrictions.Updatable !== false) { + const type = modelElement(element.$Type); + const operation = { + summary: updateRestrictions.Description || operationSummary('Changes', name, sourceName, level, element.$Collection, byKey), + tags: [sourceName], + requestBody: { + description: type && type[voc.Core.Description] || 'New property values', + required: true, + content: { + 'application/json': { + schema: ref(element.$Type, SUFFIX.update), + } + } + }, + responses: response(204, "Success", undefined, updateRestrictions.ErrorResponses, !countRestrictions), + }; + if (updateRestrictions.LongDescription) operation.description = updateRestrictions.LongDescription; + customParameters(operation, updateRestrictions); + const updateMethod = updateRestrictions.UpdateMethod ? updateRestrictions.UpdateMethod.toLowerCase() : "patch"; + pathItem[updateMethod] = operation; + } + } + + /** + * Construct Operation Object for delete + * @param {object} pathItem Path Item Object to augment + * @param {object} element Model element of navigation segment + * @param {string} name Name of navigation segment + * @param {string} sourceName Name of path source + * @param {string} target Target container child of path + * @param {integer} level Number of navigation segments so far + * @param {object} restrictions Navigation property restrictions of navigation segment + * @param {boolean} byKey Delete by key + */ + function operationDelete(pathItem, element, name, sourceName, target, level, restrictions, byKey) { + const deleteRestrictions = restrictions.DeleteRestrictions || target && target[voc.Capabilities.DeleteRestrictions] || {}; + let countRestrictions = target && (target[voc.Capabilities.CountRestrictions]?.Countable === false); + if (deleteRestrictions.Deletable !== false) { + pathItem.delete = { + summary: deleteRestrictions.Description || operationSummary('Deletes', name, sourceName, level, element.$Collection, byKey), + tags: [sourceName], + responses: response(204, "Success", undefined, deleteRestrictions.ErrorResponses, !countRestrictions), + }; + if (deleteRestrictions.LongDescription) pathItem.delete.description = deleteRestrictions.LongDescription; + customParameters(pathItem.delete, deleteRestrictions); + } + } + + /** + * Add paths and Path Item Objects for navigation segments + * @param {object} paths The Paths Object to augment + * @param {string} prefix Prefix for path + * @param {Array} prefixParameters Parameter Objects for prefix + * @param {object} type Entity type object of navigation segment + * @param {string} sourceName Name of path source + * @param {integer} level Number of navigation segments so far + * @param {string} navigationPrefix Path for finding navigation restrictions + */ + function pathItemsWithNavigation(paths, prefix, prefixParameters, type, root, sourceName, level, navigationPrefix) { + const navigationRestrictions = root[voc.Capabilities.NavigationRestrictions] || {}; + const rootNavigable = level == 0 && enumMember(navigationRestrictions.Navigability) != 'None' + || level == 1 && enumMember(navigationRestrictions.Navigability) != 'Single' + || level > 1; + + if (type && level < maxLevels) { + const properties = navigationPathMap(type); + Object.keys(properties).forEach(name => { + const parentRestrictions = navigationPropertyRestrictions(root, navigationPrefix); + if (enumMember(parentRestrictions.Navigability) == 'Single') return; + + const navigationPath = navigationPrefix + (navigationPrefix.length > 0 ? '/' : '') + name; + const restrictions = navigationPropertyRestrictions(root, navigationPath); + if (['Recursive', 'Single'].includes(enumMember(restrictions.Navigability)) + || restrictions.Navigability == null && rootNavigable) { + const targetSetName = root.$NavigationPropertyBinding && root.$NavigationPropertyBinding[navigationPath]; + const target = entityContainer[targetSetName]; + const targetType = target && modelElement(target.$Type); + const targetName = (targetType && targetType[voc.Common.Label]) || targetSetName; + pathItems(paths, prefix + '/' + name, prefixParameters, properties[name], root, sourceName, targetName, target, level + 1, navigationPath); + } + }); + } + } + + /** + * Collect navigation paths of a navigation segment and its potentially structured components + * @param {object} type Structured type + * @param {object} map Map of navigation property paths and their types + * @param {string} prefix Navigation prefix + * @param {integer} level Number of navigation segments so far + * @return {object} Map of navigation property paths and their types + */ + function navigationPathMap(type, map = {}, prefix = '', level = 0) { + const properties = propertiesOfStructuredType(type); + Object.keys(properties).forEach(key => { + if (properties[key].$Kind == 'NavigationProperty') { + map[prefix + key] = properties[key]; + } else if (properties[key].$Type && !properties[key].$Collection && level < maxLevels) { + navigationPathMap(modelElement(properties[key].$Type), map, prefix + key + '/', level + 1); + } + }) + return map; + } + + /** + * Construct map of key names for an entity type + * @param {object} type Entity type object + * @return {object} Map of key names + */ + function keyMap(type) { + const map = {}; + if (type.$Kind == 'EntityType') { + const keys = getKey(type) || []; + keys.forEach(key => { + if (typeof key == 'string') + map[key] = true; + }); + } + return map; + } + + /** + * Key for path item + * @param {object} entityType Entity Type object + * @return {array} Key of entity type or null + */ + function getKey(entityType) { + let type = entityType; + let keys = null; + while (type) { + keys = type.$Key; + if (keys || !type.$BaseType) break; + type = modelElement(type.$BaseType); + } + return keys; + } + + /** + * Key for path item + * @param {object} entityType Entity Type object + * @param {integer} level Number of navigation segments so far + * @return {object} key: Key segment, parameters: key parameters + */ + function entityKey(entityType, level) { + let segment = ''; + const params = []; + const keys = getKey(entityType) || []; + const properties = propertiesOfStructuredType(entityType); + + keys.forEach((key, index) => { + const suffix = level > 0 ? '_' + level : ''; + if (keyAsSegment) + segment += '/'; + else { + if (index > 0) segment += ','; + if (keys.length != 1) segment += key + '='; + } + let parameter; + let property = {}; + if (typeof key == 'string') { + parameter = key; + property = properties[key]; + } else { + parameter = Object.keys(key)[0]; + const segments = key[parameter].split('/'); + property = properties[segments[0]]; + for (let i = 1; i < segments.length; i++) { + const complexType = modelElement(property.$Type); + const properties = propertiesOfStructuredType(complexType); + property = properties[segments[i]]; + } + } + const propertyType = property.$Type; + segment += pathValuePrefix(propertyType) + '{' + parameter + suffix + '}' + pathValueSuffix(propertyType); + const param = { + description: [property[voc.Core.Description], property[voc.Core.LongDescription]].filter(t => t).join(' \n') + || 'key: ' + parameter, + in: 'path', + name: parameter + suffix, + required: true, + schema: getSchema(property, '', true) + }; + params.push(param); + }) + return { segment: (keyAsSegment ? '' : '(') + segment + (keyAsSegment ? '' : ')'), parameters: params }; + } + + /** + * Prefix for key value in key segment + * @param {typename} Qualified name of key property type + * @return {string} value prefix + */ + function pathValuePrefix(typename) { + //TODO: handle other Edm types, enumeration types, and type definitions + if (['Edm.Int64', 'Edm.Int32', 'Edm.Int16', 'Edm.SByte', 'Edm.Byte', + 'Edm.Double', 'Edm.Single', 'Edm.Date', 'Edm.DateTimeOffset', 'Edm.Guid'].includes(typename)) return ''; + if (keyAsSegment) return ''; + return `'`; + } + + /** + * Suffix for key value in key segment + * @param {typename} Qualified name of key property type + * @return {string} value prefix + */ + function pathValueSuffix(typename) { + //TODO: handle other Edm types, enumeration types, and type definitions + if (['Edm.Int64', 'Edm.Int32', 'Edm.Int16', 'Edm.SByte', 'Edm.Byte', + 'Edm.Double', 'Edm.Single', 'Edm.Date', 'Edm.DateTimeOffset', 'Edm.Guid'].includes(typename)) return ''; + if (keyAsSegment) return ''; + return `'`; + } + + /** + * Add path and Path Item Object for actions and functions bound to the element + * @param {object} paths Paths Object to augment + * @param {string} prefix Prefix for path + * @param {Array} prefixParameters Parameter Objects for prefix + * @param {object} element Model element the operations are bound to + * @param {string} sourceName Name of path source + * @param {boolean} byKey read by key + */ + function pathItemsForBoundOperations(paths, prefix, prefixParameters, element, sourceName, byKey = false) { + //ignore operations on navigation path + if (element.$Kind === "NavigationProperty") { + return; + } + const overloads = boundOverloads[element.$Type + (!byKey && element.$Collection ? '-c' : '')] || []; + overloads.forEach(item => { + if (item.overload.$Kind == 'Action') + pathItemAction(paths, prefix + '/' + item.name, prefixParameters, item.name, item.overload, sourceName); + else + pathItemFunction(paths, prefix + '/' + item.name, prefixParameters, item.name, item.overload, sourceName); + }); + } + + /** + * Add path and Path Item Object for an action import + * @param {object} paths Paths Object to augment + * @param {string} name Name of action import + * @param {object} child Action import object + */ + function pathItemActionImport(paths, name, child) { + const overload = modelElement(child.$Action).find(pOverload => !pOverload.$IsBound); + pathItemAction(paths, '/' + name, [], child.$Action, overload, child.$EntitySet, child); + } + + /** + * Add path and Path Item Object for action overload + * @param {object} paths Paths Object to augment + * @param {string} prefix Prefix for path + * @param {Array} prefixParameters Parameter Objects for prefix + * @param {string} actionName Qualified name of function + * @param {object} overload Function overload + * @param {string} sourceName Name of path source + * @param {string} actionImport Action import + */ + function pathItemAction(paths, prefix, prefixParameters, actionName, overload, sourceName, actionImport = {}) { + const name = actionName.indexOf('.') === -1 ? actionName : nameParts(actionName).name; + const pathItem = { + post: { + summary: actionImport[voc.Core.Description] || overload[voc.Core.Description] || 'Invokes action ' + name, + tags: [overload[voc.Common.Label] || sourceName || 'Service Operations'], + responses: overload.$ReturnType ? response(200, "Success", overload.$ReturnType, overload[voc.Capabilities.OperationRestrictions]?.ErrorResponses) + : response(204, "Success", undefined, overload[voc.Capabilities.OperationRestrictions]?.ErrorResponses), + } + }; + const actionExtension = getExtensions(overload, 'operation'); + if (Object.keys(actionExtension).length > 0) { + Object.assign(pathItem.post, actionExtension); + } + const description = actionImport[voc.Core.LongDescription] || overload[voc.Core.LongDescription]; + if (description) pathItem.post.description = description; + if (prefixParameters.length > 0) pathItem.post.parameters = [...prefixParameters]; + let parameters = overload.$Parameter || []; + if (overload.$IsBound) parameters = parameters.slice(1); + if (parameters.length > 0) { + const requestProperties = {}; + parameters.forEach(p => { requestProperties[p.$Name] = getSchema(p) }); + pathItem.post.requestBody = { + description: 'Action parameters', + content: { + 'application/json': { + schema: { + type: 'object', + properties: requestProperties + } + } + } + } + } + customParameters(pathItem.post, overload[voc.Capabilities.OperationRestrictions] || {}); + paths[prefix] = pathItem; + } + + /** + * Add path and Path Item Object for an action import + * @param {object} paths Paths Object to augment + * @param {string} name Name of function import + * @param {object} child Function import object + */ + function pathItemFunctionImport(paths, name, child) { + const overloads = modelElement(child.$Function); + console.assert(overloads, 'Unknown function "' + child.$Function + '" in function import "' + name + '"'); + overloads && overloads.filter(overload => !overload.$IsBound).forEach(overload => pathItemFunction(paths, '/' + name, [], child.$Function, overload, child.$EntitySet, child)); + } + + /** + * Add path and Path Item Object for function overload + * @param {object} paths Paths Object to augment + * @param {string} prefix Prefix for path + * @param {Array} prefixParameters Parameter Objects for prefix + * @param {string} functionName Qualified name of function + * @param {object} overload Function overload + * @param {string} sourceName Name of path source + * @param {object} functionImport Function Import + */ + function pathItemFunction(paths, prefix, prefixParameters, functionName, overload, sourceName, functionImport = {}) { + const name = functionName.indexOf('.') === -1 ? functionName : nameParts(functionName).name; + let parameters = overload.$Parameter || []; + if (overload.$IsBound) parameters = parameters.slice(1); + const pathSegments = []; + const params = []; + + const implicitAliases = csdl.$Version > '4.0' || parameters.some(p => p[voc.Core.OptionalParameter]); + + parameters.forEach(p => { + const param = { + required: implicitAliases ? !p[voc.Core.OptionalParameter] : true + }; + const description = [p[voc.Core.Description], p[voc.Core.LongDescription]].filter(t => t).join(' \n'); + if (description) param.description = description; + const type = modelElement(p.$Type || 'Edm.String'); + // TODO: check whether parameter or type definition of Edm.Stream is annotated with JSON.Schema + if (p.$Collection || p.$Type == 'Edm.Stream' + || type && ['ComplexType', 'EntityType'].includes(type.$Kind) + || type && type.$UnderlyingType == 'Edm.Stream') { + param.in = 'query'; + if ( + implicitAliases && + csdl.$Version !== '2.0' && + SYSTEM_QUERY_OPTIONS.includes(p.$Name.toLowerCase()) + ) { + param.name = '@' + p.$Name; + } else if (implicitAliases) { + param.name = p.$Name; + } else { + pathSegments.push(p.$Name + '=@' + p.$Name); + param.name = '@' + p.$Name; + } + param.schema = { type: 'string' }; + if (description) param.description += ' \n'; else param.description = ''; + param.description += 'This is ' + + (p.$Collection ? 'a ' : '') + + 'URL-encoded JSON ' + + (p.$Collection ? 'array with items ' : '') + + 'of type ' + + namespaceQualifiedName(p.$Type || 'Edm.String') + + ', see [Complex and Collection Literals](https://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part2-url-conventions.html#sec_ComplexandCollectionLiterals)'; + param.example = p.$Collection ? '[]' : '{}'; + } else { + if (implicitAliases) { + param.in = 'query'; + } else { + pathSegments.push(p.$Name + "={" + p.$Name + "}"); + param.in = 'path'; + } + if ( + implicitAliases && + csdl.$Version !== '2.0' && + SYSTEM_QUERY_OPTIONS.includes(p.$Name.toLowerCase()) + ) + param.name = '@' + p.$Name; + else + param.name = p.$Name; + if (!p.$Type || p.$Type === "Edm.String" || (type && (!type.$Type || type.$Type === "Edm.String"))) { + if (description) param.description += " \n"; + else param.description = ""; + param.description += "String value needs to be enclosed in single quotes"; + } + param.schema = getSchema(p, '', true, true); + } + params.push(param); + }); + + const pathParameters = implicitAliases ? '' : '(' + pathSegments.join(',') + ')'; + const pathItem = { + get: { + summary: functionImport[voc.Core.Description] || overload[voc.Core.Description] || 'Invokes function ' + name, + tags: [overload[voc.Common.Label] || sourceName || 'Service Operations'], + parameters: prefixParameters.concat(params), + responses: response(200, "Success", overload.$ReturnType, overload[voc.Capabilities.OperationRestrictions]?.ErrorResponses), + } + }; + const functionExtension = getExtensions(overload, 'operation'); + if (Object.keys(functionExtension).length > 0) { + Object.assign(pathItem.get, functionExtension); + } + const iDescription = functionImport[voc.Core.LongDescription] || overload[voc.Core.LongDescription]; + if (iDescription) pathItem.get.description = iDescription; + customParameters(pathItem.get, overload[voc.Capabilities.OperationRestrictions] || {}); + paths[prefix + pathParameters] = pathItem; + } + + /** + * Add path and Path Item Object for batch requests + * @param {object} paths Paths Object to augment + * @param {object} container Entity container + */ + function pathItemBatch(paths, container) { + const batchSupport = container[voc.Capabilities.BatchSupport] || {}; + const supported = container[voc.Capabilities.BatchSupported] !== false && batchSupport.Supported !== false; + if (supported) { + const firstEntitySet = Object.keys(container).filter(child => isIdentifier(child) && container[child].$Collection)[0]; + paths['/$batch'] = { + post: { + summary: batchSupport[voc.Core.Description] || 'Sends a group of requests', + description: (batchSupport[voc.Core.LongDescription] || 'Group multiple requests into a single request payload, see ' + + '[Batch Requests](http://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part1-protocol.html#sec_BatchRequests).') + + '\n\n*Please note that "Try it out" is not supported for this request.*', + tags: ['Batch Requests'], + requestBody: { + required: true, + description: 'Batch request', + content: { + 'multipart/mixed;boundary=request-separator': { + schema: { + type: 'string' + }, + example: '--request-separator\n' + + 'Content-Type: application/http\n' + + 'Content-Transfer-Encoding: binary\n\n' + + 'GET ' + firstEntitySet + ' HTTP/1.1\n' + + 'Accept: application/json\n\n' + + '\n--request-separator--' + } + } + }, + responses: { + '4XX': { + $ref: '#/components/responses/error' + } + } + } + }; + paths['/$batch'].post.responses[csdl.$Version < '4.0' ? 202 : 200] = { + description: 'Batch response', + content: { + 'multipart/mixed': { + schema: { + type: 'string' + }, + example: '--response-separator\n' + + 'Content-Type: application/http\n\n' + + 'HTTP/1.1 200 OK\n' + + 'Content-Type: application/json\n\n' + + '{...}' + + '\n--response-separator--' + } + } + }; + } + } + + /** + * Construct Responses Object + * @param {string} code HTTP response code + * @param {string} description Description + * @param {object} type Response type object + * @param {array} errors Array of operation-specific status codes with descriptions + */ + function response(code, description, type, errors, isCount = true) { + const r = {}; + r[code] = { + description: description + }; + let CountPropertyObj = { [csdl.$Version > '4.0' ? '@count' : '@odata.count']: ref('count') }; + if (code != 204) { + const s = getSchema(type); + r[code].content = { + 'application/json': {} + }; + + if (type.$Collection) { + r[code].content['application/json'].schema = { + type: 'object', + title: 'Collection of ' + nameParts(type.$Type ? type.$Type : 'Edm.String').name, + properties: { + ...(isCount && CountPropertyObj), + value: s + } + }; + } + + else if ( + type.$Type === undefined || + (type.$Type.startsWith("Edm.") && + !["Edm.Stream", "Edm.EntityType", "Edm.ComplexType"].includes( + type.$Type, + )) + ) { + r[code].content['application/json'].schema = { type: "object", properties: { value: s } }; + } + + else { + r[code].content['application/json'].schema = s; + } + } + if (errors) { + for (const e of errors) { + r[e.StatusCode] = { + description: e.Description, + content: { + "application/json": { + schema: { $ref: "#/components/schemas/error" }, + }, + }, + }; + } + } else { + r["4XX"] = { + $ref: "#/components/responses/error", + }; + } + return r; + } + + /** + * Construct the Components Object from the types of the CSDL document + * @param {object} csdl CSDL document + * @param {object} entityContainer Entity Container object + * @return {object} Components Object + */ + function getComponents(csdl, entityContainer) { + const c = { + schemas: getSchemas(csdl) + }; + + if (csdl.$EntityContainer) { + c.parameters = getParameters(); + c.responses = { + error: { + description: 'Error', + content: { + 'application/json': { + schema: ref('error') + } + } + } + }; + } + + getSecuritySchemes(c, entityContainer) + + return c; + } + + /** + * Construct Schema Objects from the types of the CSDL document + * @param {object} csdl CSDL document + * @return {object} Map of Schema Objects + */ + function getSchemas(csdl) { + const unordered = {}; + + for (const r of requiredSchemas.list) { + const type = modelElement(`${r.namespace}.${r.name}`); + if (!type) continue; + switch (type.$Kind) { + case "ComplexType": + case "EntityType": + schemasForStructuredType(unordered, r.namespace, r.name, type, r.suffix); + break; + case "EnumType": + schemaForEnumerationType(unordered, r.namespace, r.name, type); + break; + case "TypeDefinition": + schemaForTypeDefinition(unordered, r.namespace, r.name, type); + break; + } + } + + // Add @OpenAPI.Extensions at entity level to schema object + Object.keys(csdl).filter(name => isIdentifier(name)).forEach(namespace => { + const schema = csdl[namespace]; + Object.keys(schema).filter(name => isIdentifier(name)).forEach(name => { + const type = schema[name]; + if (type.$Kind === 'EntityType' || type.$Kind === 'ComplexType') { + const schemaName = namespace + "." + name + SUFFIX.read; + const extensions = getExtensions(type, 'schema'); + if (Object.keys(extensions).length > 0) { + unordered[schemaName] = unordered[schemaName] || {}; + Object.assign(unordered[schemaName], extensions); + } + } + }); + }); + + const ordered = {}; + for (const name of Object.keys(unordered).sort()) { + ordered[name] = unordered[name]; + } + + inlineTypes(ordered); + + if (csdl.$EntityContainer) { + ordered.count = count(); + ordered.error = error(); + } + + return ordered; + } + + /** + * Construct Schema Objects from the types of the CSDL document + * @param {object} schemas Map of Schema Objects to augment + */ + function inlineTypes(schemas) { + if (typesToInline.geoPoint) { + schemas.geoPoint = { + type: 'object', + properties: { + coordinates: ref('geoPosition'), + type: { + type: 'string', + enum: ['Point'], + default: 'Point' + } + }, + required: ['type', 'coordinates'] + }; + schemas.geoPosition = { + type: 'array', + minItems: 2, + items: { + type: 'number' + } + } + } + } + + /** + * Construct Schema Objects for an enumeration type + * @param {object} schemas Map of Schema Objects to augment + * @param {string} qualifier Qualifier for structured type + * @param {string} name Simple name of structured type + * @param {object} type Structured type + * @return {object} Map of Schemas Objects + */ + function schemaForEnumerationType(schemas, qualifier, name, type) { + const members = []; + Object.keys(type).filter(iName => isIdentifier(iName)).forEach(iName2 => { + members.push(iName2); + }); + + const s = { + type: 'string', + title: name, + enum: members + }; + const description = type[voc.Core.LongDescription]; + if (description) s.description = description; + schemas[qualifier + '.' + name] = s; + } + + /** + * Construct Schema Objects for a type definition + * @param {object} schemas Map of Schema Objects to augment + * @param {string} qualifier Qualifier for structured type + * @param {string} name Simple name of structured type + * @param {object} type Structured type + * @return {object} Map of Schemas Objects + */ + function schemaForTypeDefinition(schemas, qualifier, name, type) { + const s = getSchema(Object.assign({ $Type: type.$UnderlyingType }, type)); + s.title = name; + const description = type[voc.Core.LongDescription]; + if (description) s.description = description; + schemas[qualifier + '.' + name] = s; + } + + /** + * Construct Schema Objects for a structured type + * @param {object} schemas Map of Schema Objects to augment + * @param {string} qualifier Qualifier for structured type + * @param {string} name Simple name of structured type + * @param {string} suffix Suffix for read/create/update + * @param {object} type Structured type + * @return {object} Map of Schemas Objects + */ + function schemasForStructuredType(schemas, qualifier, name, type, suffix) { + const schemaName = qualifier + "." + name + suffix; + const baseName = qualifier + "." + name; + const isKey = keyMap(type); + const required = Object.keys(isKey); + const schemaProperties = {}; + let isCount = true; + if (csdl[qualifier]?.$Annotations) { + const annotations = csdl[qualifier].$Annotations[`${qualifier}.EntityContainer/${name}`]; + if (annotations && annotations[voc.Capabilities.CountRestrictions] && annotations[voc.Capabilities.CountRestrictions]?.Countable === false) { + isCount = false; + } + } + const properties = propertiesOfStructuredType(type); + Object.keys(properties).forEach(iName => { + const property = properties[iName]; + if (suffix === SUFFIX.read) schemaProperties[iName] = getSchema(property); + if ((Object.prototype.hasOwnProperty.call(property, '@Common.FieldControl')) && property['@Common.FieldControl'] === 'Mandatory') { required.push(iName) } + if (property.$Kind == 'NavigationProperty') { + if (property.$Collection && suffix === "" && isCount === true) { + schemaProperties[`${iName}@${csdl.$Version === '4.0' ? 'odata.' : ''}count`] = ref('count'); + } + if (property[voc.Core.Permissions] != "Read" && !property[voc.Core.Computed] && (property.$ContainsTarget || property.$OnDelete === 'Cascade')) { + if (suffix === SUFFIX.create) + schemaProperties[iName] = getSchema(property, SUFFIX.create); + if (suffix === SUFFIX.update) + schemaProperties[iName] = getSchema(property, SUFFIX.create); + } + } else { + if (property[voc.Core.Permissions] === "Read" || property[voc.Core.Computed] || property[voc.Core.ComputedDefaultValue]) { + let index = required.indexOf(iName); + if (index != -1) required.splice(index, 1); + } + if (!(property[voc.Core.Permissions] === "Read" || property[voc.Core.Computed])) { + if (suffix === SUFFIX.create) + schemaProperties[iName] = getSchema(property, SUFFIX.create); + if (suffix === SUFFIX.update && !isKey[iName] && !property[voc.Core.Immutable]) + schemaProperties[iName] = getSchema(property, SUFFIX.update); + } + } + }); + + + schemas[schemaName] = { + title: (type[voc.Core.Description] || name) + TITLE_SUFFIX[suffix], + type: 'object' + }; + if (Object.keys(schemaProperties).length > 0) + schemas[schemaName].properties = schemaProperties; + + if (suffix === SUFFIX.read && type["@ODM.root"]) schemas[schemaName]["x-sap-root-entity"] = type["@ODM.root"] + odmExtensions(type, schemas[schemaName]); + erExtensions(type, schemas[schemaName]); + + if (suffix === SUFFIX.create && required.length > 0) + schemas[schemaName].required = [...new Set(required)]; + + const description = type[voc.Core.LongDescription]; + if (description) { + schemas[schemaName].description = description; + } + + if (derivedTypes[baseName]) { + schemas[schemaName].anyOf = []; + derivedTypes[baseName].forEach((derivedType) => { + schemas[schemaName].anyOf.push(ref(derivedType, suffix)); + }); + if (!type.$Abstract) schemas[schemaName].anyOf.push({}); + } + } + + /** + * Add ODM extensions to OpenAPI schema for a structured type + * @param {object} type Structured type + * @param {object} schema OpenAPI schema to augment + */ + function odmExtensions(type, schema) { + for (const [annotation, openApiExtension] of Object.entries(ODM_ANNOTATIONS)) { + if (type[annotation]) schema[openApiExtension] = type[annotation]; + } + } + + /** + * Add entity relationship extensions to OpenAPI schema for a structured type + * @param {object} type Structured type + * @param {object} schema OpenAPI schema to augment + */ + function erExtensions(type, schema) { + for (const [annotation, openApiExtension] of Object.entries(ER_ANNOTATIONS)) { + if (type[annotation]) schema[openApiExtension] = type[annotation]; + } + } + + /** + * Collect all properties of a structured type along the inheritance hierarchy + * @param {object} type Structured type + * @return {object} Map of properties + */ + function propertiesOfStructuredType(type) { + const properties = (type && type.$BaseType) ? propertiesOfStructuredType(modelElement(type.$BaseType)) : {}; + if (type) { + Object.keys(type).filter(name => isIdentifier(name)).forEach(name => { + properties[name] = type[name]; + }); + } + return properties; + } + + /** + * Construct Parameter Objects for type-independent OData system query options + * @return {object} Map of Parameter Objects + */ + function getParameters() { + const param = { + top: { + name: queryOptionPrefix + 'top', + in: 'query', + description: 'Show only the first n items, see [Paging - Top](http://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part1-protocol.html#sec_SystemQueryOptiontop)', + schema: { + type: 'integer', + minimum: 0 + }, + example: 50 + }, + skip: { + name: queryOptionPrefix + 'skip', + in: 'query', + description: 'Skip the first n items, see [Paging - Skip](http://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part1-protocol.html#sec_SystemQueryOptionskip)', + schema: { + type: 'integer', + minimum: 0 + } + }, + count: { + name: queryOptionPrefix + 'count', + in: 'query', + description: 'Include count of items, see [Count](http://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part1-protocol.html#sec_SystemQueryOptioncount)', + schema: { + type: 'boolean' + } + } + }; + + if (csdl.$Version >= '4.0') param.search = { + name: queryOptionPrefix + 'search', + in: 'query', + description: 'Search items by search phrases, see [Searching](http://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part1-protocol.html#sec_SystemQueryOptionsearch)', + schema: { + type: 'string' + } + }; + + return param; + } + + /** + * Construct OData error response + * @return {object} Error response schema + */ + function error() { + const err = { + type: 'object', + required: ['error'], + properties: { + error: { + type: 'object', + required: ['code', 'message'], + properties: { + code: { type: 'string' }, + message: { type: 'string' }, + target: { type: 'string' }, + details: { + type: 'array', + items: { + type: 'object', + required: ['code', 'message'], + properties: { + code: { type: 'string' }, + message: { type: 'string' }, + target: { type: 'string' } + } + } + }, + innererror: { + type: 'object', + description: 'The structure of this object is service-specific' + } + } + } + } + }; + + if (csdl.$Version < '4.0') { + err.properties.error.properties.message = { + type: 'object', + properties: { + lang: { type: 'string' }, + value: { type: 'string' } + }, + required: ['lang', 'value'] + }; + delete err.properties.error.properties.details; + delete err.properties.error.properties.target; + } + + return err; + } + + /** + * Construct OData count response + * @return {object} Count response schema + */ + function count() { + return { + anyOf: [ + { type: 'number' }, + { type: 'string' } + ], + description: 'The number of entities in the collection. Available when using the [$count](http://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part1-protocol.html#sec_SystemQueryOptioncount) query option.', + }; + } + + /** + * Construct Schema Object for model object referencing a type + * @param {object} modelElement referencing a type + * @return {object} Schema Object + */ + function getSchema(element, suffix = '', forParameter = false, forFunction = false) { + let s = {}; + switch (element.$Type) { + case 'Edm.AnnotationPath': + case 'Edm.ModelElementPath': + case 'Edm.NavigationPropertyPath': + case 'Edm.PropertyPath': + s.type = 'string'; + break; + case 'Edm.Binary': + s = { + type: 'string', + format: 'base64url' + }; + if (element.$MaxLength) s.maxLength = Math.ceil(4 * element.$MaxLength / 3); + break; + case 'Edm.Boolean': + s.type = 'boolean'; + break; + case 'Edm.Byte': + s = { + type: 'integer', + format: 'uint8' + }; + break; + case 'Edm.Date': + s = { + type: 'string', + format: 'date', + example: '2017-04-13' + }; + break; + case 'Edm.DateTime': + case 'Edm.DateTimeOffset': + s = { + type: 'string', + format: 'date-time', + example: '2017-04-13T15:51:04' + (isNaN(element.$Precision) || element.$Precision === 0 ? '' : '.' + '0'.repeat(element.$Precision)) + 'Z' + }; + break; + case 'Edm.Decimal': + s = { + anyOf: [{ type: 'number', format: 'decimal' }, { type: 'string' }], + example: 0 + }; + if (!isNaN(element.$Precision)) s['x-sap-precision'] = element.$Precision; + if (!isNaN(element.$Scale)) s['x-sap-scale'] = element.$Scale; + // eslint-disable-next-line no-case-declarations + let scale = !isNaN(element.$Scale) ? element.$Scale : null; + if (scale !== null) { + // Node.js 12.13.0 has problems with negative exponents, 10 ** -5 --> 0.000009999999999999999 + if (scale <= 0) + s.anyOf[0].multipleOf = 10 ** -scale; + else + s.anyOf[0].multipleOf = 1 / 10 ** scale; + } + if (element.$Precision < 16) { + let limit = 10 ** (element.$Precision - scale); + let delta = 10 ** -scale; + s.anyOf[0].maximum = limit - delta; + s.anyOf[0].minimum = -s.anyOf[0].maximum; + } + break; + case 'Edm.Double': + s = { + anyOf: [{ type: 'number', format: 'double' }, { type: 'string' }], + example: 3.14 + }; + break; + case 'Edm.Duration': + s = { + type: 'string', + format: 'duration', + example: 'P4DT15H51M04S' + }; + break; + case 'Edm.GeographyPoint': + case 'Edm.GeometryPoint': + s = ref('geoPoint'); + typesToInline.geoPoint = true; + break; + case 'Edm.Guid': + s = { + type: 'string', + format: 'uuid', + example: '01234567-89ab-cdef-0123-456789abcdef' + }; + break; + case 'Edm.Int16': + s = { + type: 'integer', + format: 'int16' + }; + break; + case 'Edm.Int32': + s = { + type: 'integer', + format: 'int32' + }; + break; + case 'Edm.Int64': + s = { + anyOf: [{ type: 'integer', format: 'int64' }, { type: 'string' }], + example: "42" + }; + break; + case 'Edm.PrimitiveType': + s = { + anyOf: [{ type: 'boolean' }, { type: 'number' }, { type: 'string' }] + }; + break; + case 'Edm.SByte': + s = { + type: 'integer', + format: 'int8' + }; + break; + case 'Edm.Single': + s = { + anyOf: [{ type: 'number', format: 'float' }, { type: 'string' }], + example: 3.14 + }; + break; + case 'Edm.Stream': + // eslint-disable-next-line no-case-declarations + let jsonSchema = element[voc.JSON.Schema]; + if (jsonSchema) { + if (typeof jsonSchema == 'string') + s = JSON.parse(jsonSchema); + else + s = jsonSchema; + } else { + s = { + type: 'string', + format: 'base64url' + }; + } + break; + case 'Edm.String': + case undefined: + s.type = 'string'; + if (element.$MaxLength) s.maxLength = element.$MaxLength; + getPattern(s, element); + break; + case 'Edm.TimeOfDay': + s = { + type: 'string', + format: 'time', + example: '15:51:04' + }; + break; + default: + if (element.$Type.startsWith('Edm.')) { + DEBUG?.('Unknown type: ' + element.$Type); + } else { + let type = modelElement(element.$Type); + let isStructured = type && ['ComplexType', 'EntityType'].includes(type.$Kind); + s = ref(element.$Type, (isStructured ? suffix : '')); + if (element.$MaxLength) { + s = { + allOf: [s], + maxLength: element.$MaxLength + }; + } + } + } + + allowedValues(s, element); + + if (element.$Nullable) { + if (s.$ref) s = { allOf: [s] }; + s.nullable = true; + } + + if (element.$DefaultValue !== undefined) { + if (s.$ref) s = { allOf: [s] }; + s.default = element.$DefaultValue; + } + + if (element[voc.Core.Example]) { + if (s.$ref) s = { allOf: [s] }; + s.example = element[voc.Core.Example].Value; + } + + if (forFunction) { + if (s.example && typeof s.example === "string") { + s.example = `${pathValuePrefix(element.$Type)}${s.example + }${pathValueSuffix(element.$Type)} `; + } + if (s.pattern) { + const pre = pathValuePrefix(element.$Type); + const suf = pathValueSuffix(element.$Type); + s.pattern = s.pattern.replace(/^\^/, `^ ${pre} (`); + s.pattern = s.pattern.replace(/\$$/, `)${suf} $`); + } else if (!element.$Type || element.$Type === "Edm.String") { + s.pattern = "^'([^']|'')*'$"; + } + if (element.$Nullable) { + s.default = "null"; + if (s.pattern) { + s.pattern = s.pattern.replace(/^\^/, "^(null|"); + s.pattern = s.pattern.replace(/\$$/, ")$"); + } + } + } + + if (element[voc.Validation.Maximum] != undefined) { + if (s.$ref) s = { allOf: [s] }; + if (s.anyOf) { + s.anyOf[0].maximum = element[voc.Validation.Maximum]; + } + if (element[voc.Validation.Maximum + voc.Validation.Exclusive]) s.exclusiveMaximum = true; + } + + if (element[voc.Validation.Minimum] != undefined) { + if (s.$ref) s = { allOf: [s] }; + if (s.anyOf) { + s.anyOf[0].minimum = element[voc.Validation.Minimum]; + } + if (element[voc.Validation.Minimum + voc.Validation.Exclusive]) s.exclusiveMinimum = true; + } + + if (element.$Collection) { + s = { + type: 'array', + items: s + }; + } + + if (!forParameter && element[voc.Core.LongDescription]) { + if (s.$ref) s = { allOf: [s] }; + s.description = element[voc.Core.LongDescription]; + } + + if (element['@ODM.oidReference']?.entityName) { + s['x-sap-odm-oid-reference-entity-name'] = element['@ODM.oidReference'].entityName + } + + for (const key in element) { + if (key.startsWith(ER_ANNOTATION_PREFIX) && ER_ANNOTATIONS[key]) { + s[ER_ANNOTATIONS[key]] = element[key]; + } + } + return s; + } + + /** + * Add allowed values enum to Schema Object for string-like model element + * @param {object} schema Schema Object to augment + * @param {object} element Model element + */ + function allowedValues(schema, element) { + const values = element[voc.Validation.AllowedValues]; + if (values) schema.enum = values.map(record => record.Value); + } + + /** + * Add pattern to Schema Object for string-like model element + * @param {object} schema Schema Object to augment + * @param {object} element Model element + */ + function getPattern(schema, element) { + const pattern = element[voc.Validation.Pattern]; + if (pattern) schema.pattern = pattern; + } + + /** + * Construct Reference Object for a type + * @param {string} typename Qualified name of referenced type + * @param {string} suffix Optional suffix for referenced schema + * @return {object} Reference Object + */ + function ref(typename, suffix = '') { + let name = typename; + let nsp = ''; + let url = ''; + if (typename.indexOf('.') != -1) { + let parts = nameParts(typename); + nsp = namespace[parts.qualifier]; + name = nsp + '.' + parts.name; + url = namespaceUrl[nsp] || ''; + if (url === "" && !requiredSchemas.used[name + suffix]) { + requiredSchemas.used[name + suffix] = true; + requiredSchemas.list.push({ namespace: nsp, name: parts.name, suffix }); + } + //TODO: introduce better way than guessing + if (url.endsWith('.xml')) url = url.substring(0, url.length - 3) + "openapi3.json"; + } + return { + $ref: url + '#/components/schemas/' + name + suffix + }; + } + + /** + * Augment Components Object with map of Security Scheme Objects + * @param {object} components Components Object to augment + * @param {object} entityContainer Entity Container object + */ + function getSecuritySchemes(components, entityContainer) { + const authorizations = entityContainer && entityContainer[voc.Authorization.Authorizations] ? entityContainer[voc.Authorization.Authorizations] : []; + const schemes = {}; + const location = { Header: 'header', QueryOption: 'query', Cookie: 'cookie' }; + authorizations.forEach(auth => { + const scheme = {}; + const flow = {}; + if (auth.Description) scheme.description = auth.Description; + const qualifiedType = auth['@type'] || auth['@odata.type'] + const type = qualifiedType.substring(qualifiedType.lastIndexOf(".") + 1); + let unknown = false + switch (type) { + case 'ApiKey': + scheme.type = 'apiKey'; + scheme.name = auth.KeyName; + scheme.in = location[auth.Location]; + break; + case 'Http': + scheme.type = 'http'; + scheme.scheme = auth.Scheme; + scheme.bearerFormat = auth.BearerFormat; + break; + case 'OAuth2AuthCode': + scheme.type = 'oauth2'; + scheme.flows = { authorizationCode: flow }; + flow.authorizationUrl = auth.AuthorizationUrl; + flow.tokenUrl = auth.TokenUrl; + if (auth.RefreshUrl) flow.refreshUrl = auth.RefreshUrl; + flow.scopes = getScopes(auth); + break; + case 'OAuth2ClientCredentials': + scheme.type = 'oauth2'; + scheme.flows = { clientCredentials: flow }; + flow.tokenUrl = auth.TokenUrl; + if (auth.RefreshUrl) flow.refreshUrl = auth.RefreshUrl; + flow.scopes = getScopes(auth); + break; + case 'OAuth2Implicit': + scheme.type = 'oauth2'; + scheme.flows = { implicit: flow }; + flow.authorizationUrl = auth.AuthorizationUrl; + if (auth.RefreshUrl) flow.refreshUrl = auth.RefreshUrl; + flow.scopes = getScopes(auth); + break; + case 'OAuth2Password': + scheme.type = 'oauth2'; + scheme.flows = {}; + scheme.flows = { password: flow }; + flow.tokenUrl = auth.TokenUrl; + if (auth.RefreshUrl) flow.refreshUrl = auth.RefreshUrl; + flow.scopes = getScopes(auth); + break; + case 'OpenIDConnect': + scheme.type = 'openIdConnect'; + scheme.openIdConnectUrl = auth.IssuerUrl; + break; + default: + unknown = true + DEBUG?.('Unknown Authorization type ' + qualifiedType); + } + if (!unknown) schemes[auth.Name] = scheme; + }); + if (Object.keys(schemes).length > 0) components.securitySchemes = schemes + } + + function getScopes(authorization) { + const scopes = {}; + authorization.Scopes.forEach(scope => { scopes[scope.Scope] = scope.Description }); + return scopes; + } + + /** + * Augment OpenAPI document with Security Requirements Object + * @param {object} openapi OpenAPI document to augment + * @param {object} entityContainer Entity Container object + */ + function security(openapi, entityContainer) { + const securitySchemes = entityContainer && entityContainer[voc.Authorization.SecuritySchemes] ? entityContainer[voc.Authorization.SecuritySchemes] : []; + // check if securitySchemas exist if it does not exist then throw a warning + if (securitySchemes.length === 0) { + DEBUG?.('No security schemes defined in the entity container'); + } + if (securitySchemes.length > 0) openapi.security = []; + securitySchemes.forEach(scheme => { + const s = {}; + s[scheme.Authorization] = scheme.RequiredScopes || []; + openapi.security.push(s); + }); + } + + /** + * a qualified name consists of a namespace or alias, a dot, and a simple name + * @param {string} qualifiedName + * @return {string} namespace-qualified name + */ + function namespaceQualifiedName(qualifiedName) { + let np = nameParts(qualifiedName); + return namespace[np.qualifier] + '.' + np.name; + } + + /** + * a qualified name consists of a namespace or alias, a dot, and a simple name + * @param {string} qualifiedName + * @return {object} with components qualifier and name + */ + function nameParts(qualifiedName) { + const pos = qualifiedName.lastIndexOf('.'); + console.assert(pos > 0, 'Invalid qualified name ' + qualifiedName); + return { + qualifier: qualifiedName.substring(0, pos), + name: qualifiedName.substring(pos + 1) + }; + } + + /** + * an identifier does not start with $ and does not contain @ + * @param {string} name + * @return {boolean} name is an identifier + */ + function isIdentifier(name) { + return !name.startsWith('$') && !name.includes('@'); + } + +}; diff --git a/lib/compile/csdl2openapi.js b/lib/compile/csdl2openapi.js index 6901a4a..c8aeeda 100644 --- a/lib/compile/csdl2openapi.js +++ b/lib/compile/csdl2openapi.js @@ -7,8 +7,43 @@ const DEBUG = cds.debug('openapi'); // Initialize cds.debug with the 'openapi' // Import modularized components const constants = require('./modules/constants'); -const { nameParts, isIdentifier, splitName, namespaceQualifiedName } = require('./modules/utils/naming'); -const validators = require('./modules/validators'); +const { nameParts, isIdentifier, splitName, namespaceQualifiedName, enumMember } = require('./modules/utils/naming'); +const validators = require('./modules/validators'); +const { + pathValuePrefix, + pathValueSuffix, + navigationPropertyPath, + propertyPath, + navigationPaths, + navigationPathMap, + primitivePaths, + buildKeyParameters, + buildPathWithKeys +} = require('./modules/builders/paths'); +const { + addQueryOptions, + optionTop, + optionSkip, + optionCount, + optionFilter, + optionOrderBy, + optionSearch, + optionSelect, + optionExpand, + buildComponentParameters +} = require('./modules/builders/parameters'); +const { + collectionResponse, + entityResponse, + operationResponse, + errorResponse, + countResponse, + batchResponse, + buildStandardResponses, + getTypeSchema, + getEdmTypeSchema, + withETag +} = require('./modules/builders/responses'); //TODO @@ -29,1474 +64,6 @@ const validators = require('./modules/validators'); // Import constants from the constants module const { SUFFIX, TITLE_SUFFIX, SYSTEM_QUERY_OPTIONS, ODM_ANNOTATIONS, ER_ANNOTATION_PREFIX, ER_ANNOTATIONS } = constants; - -/** - * Construct an OpenAPI description from a CSDL document - * @param {object} csdl CSDL document - * @param {object} options Optional parameters - * @return {object} OpenAPI description - */ -module.exports.csdl2openapi = function ( - csdl, - { - url: serviceRoot, - servers: serversObject, - odataVersion: odataVersion, - scheme: scheme = 'https', - host: host = 'localhost', - basePath: basePath = '/service-root', - diagram: diagram = false, - maxLevels: maxLevels = 5 - } = {} -) { - // as preProcess below mutates the csdl, copy it before, to avoid side-effects on the caller side - csdl = JSON.parse(JSON.stringify(csdl)) - csdl.$Version = odataVersion ? odataVersion : '4.01' - serviceRoot = serviceRoot || (scheme + '://' + host + basePath); - const queryOptionPrefix = csdl.$Version <= '4.01' ? '$' : ''; - const typesToInline = {}; // filled in schema() and used in inlineTypes() - const boundOverloads = {}; - const derivedTypes = {}; - const alias = {}; - const namespace = { 'Edm': 'Edm' }; - const namespaceUrl = {}; - const voc = {}; - const requiredSchemas = { list: [], used: {} }; - - preProcess(csdl, boundOverloads, derivedTypes, alias, namespace, namespaceUrl, voc); - - const entityContainer = csdl.$EntityContainer ? modelElement(csdl.$EntityContainer) : {}; - if (csdl.$EntityContainer) { - let serviceName = nameParts(csdl.$EntityContainer).qualifier; - Object.keys(entityContainer).forEach(element => { - if (entityContainer[element].$Type) { - let type = nameParts(entityContainer[element].$Type).name; - if ((csdl[serviceName]?.[type]?.['@cds.autoexpose'] || csdl[serviceName]?.[type]?.['@cds.autoexposed']) && !entityContainer[type]) - entityContainer[element]['$cds.autoexpose'] = true; - } - }); - } - - const keyAsSegment = entityContainer ? entityContainer[voc.Capabilities.KeyAsSegmentSupported] : {}; - - const openapi = { - openapi: '3.0.2', - info: getInfo(csdl, entityContainer), - 'x-sap-api-type': 'ODATAV4', - 'x-odata-version': csdl.$Version, - 'x-sap-shortText': getShortText(csdl, entityContainer), - servers: getServers(serviceRoot, serversObject), - tags: entityContainer ? getTags(entityContainer) : {}, - paths: entityContainer ? getPaths(entityContainer) : {}, - components: getComponents(csdl, entityContainer) - }; - - const externalDocs = getExternalDoc(csdl); - if (externalDocs && Object.keys(externalDocs).length > 0) { - openapi.externalDocs = externalDocs; - } - const extensions = getExtensions(csdl, 'root'); - if (extensions && Object.keys(extensions).length > 0) { - Object.assign(openapi, extensions); - } - - // function to read @OpenAPI.Extensions and get them in the generated openAPI document - function getExtensions(csdl, level) { - let extensionObj = {}; - let containerSchema = {}; - if (level ==='root'){ - const namespace = csdl.$EntityContainer ? nameParts(csdl.$EntityContainer).qualifier : null; - containerSchema = csdl.$EntityContainer ? csdl[namespace] : {}; - } - else if(level === 'schema' || level === 'operation'){ - containerSchema = csdl; - } - - for (const [key, value] of Object.entries(containerSchema)) { - if (key.startsWith('@OpenAPI.Extensions')) { - const annotationProperties = key.split('@OpenAPI.Extensions.')[1]; - const keys = annotationProperties.split('.'); - if (!keys[0].startsWith("x-sap-")) { - keys[0] = (keys[0].startsWith("sap-") ? "x-" : "x-sap-") + keys[0]; - } - if (keys.length === 1) { - extensionObj[keys[0]] = value; - } else { - nestedAnnotation(extensionObj, keys[0], keys, value); - } - } - } - let extensionEnums = { - "x-sap-compliance-level": {allowedValues: ["sap:base:v1", "sap:core:v1", "sap:core:v2" ] } , - "x-sap-api-type": {allowedValues: [ "ODATA", "ODATAV4", "REST" , "SOAP"] }, - "x-sap-direction": {allowedValues: ["inbound", "outbound", "mixed"] , default : "inbound" }, - "x-sap-dpp-entity-semantics": {allowedValues: ["sap:DataSubject", "sap:DataSubjectDetails", "sap:Other"] }, - "x-sap-dpp-field-semantics": {allowedValues: ["sap:DataSubjectID", "sap:ConsentID", "sap:PurposeID", "sap:ContractRelatedID", "sap:LegalEntityID", "sap:DataControllerID", "sap:UserID", "sap:EndOfBusinessDate", "sap:BlockingDate", "sap:EndOfRetentionDate"] }, - }; - checkForExtentionEnums(extensionObj, extensionEnums); - - let extenstionSchema = { - "x-sap-stateInfo": ['state', 'deprecationDate', 'decomissionedDate', 'link'], - "x-sap-ext-overview": ['name', 'values'], - "x-sap-deprecated-operation" : ['deprecationDate', 'successorOperationRef', "successorOperationId"], - "x-sap-odm-semantic-key" : ['name', 'values'], - }; - - checkForExtentionSchema(extensionObj, extenstionSchema); - return extensionObj; - } - - function checkForExtentionEnums(extensionObj, extensionEnums){ - for (const [key, value] of Object.entries(extensionObj)) { - if(extensionEnums[key] && extensionEnums[key].allowedValues && !extensionEnums[key].allowedValues.includes(value)){ - if(extensionEnums[key].default){ - extensionObj[key] = extensionEnums[key].default; - } - else{ - delete extensionObj[key]; - } - } - } - } - - function checkForExtentionSchema(extensionObj, extenstionSchema) { - for (const [key, value] of Object.entries(extensionObj)) { - if (extenstionSchema[key]) { - if (Array.isArray(value)) { - extensionObj[key] = value.filter((v) => extenstionSchema[key].includes(v)); - } else if (typeof value === "object" && value !== null) { - for (const field in value) { - if (!extenstionSchema[key].includes(field)) { - delete extensionObj[key][field]; - } - } - } - } - } - } - - - function nestedAnnotation(resObj, openapiProperty, keys, value) { - if (resObj[openapiProperty] === undefined) { - resObj[openapiProperty] = {}; - } - - let node = resObj[openapiProperty]; - - // traverse the annotation property and define the objects if they're not defined - for (let nestedIndex = 1; nestedIndex < keys.length - 1; nestedIndex++) { - const nestedElement = keys[nestedIndex]; - if (node[nestedElement] === undefined) { - node[nestedElement] = {}; - } - node = node[nestedElement]; - } - - // set value annotation property - node[keys[keys.length - 1]] = value; - } - - if (!csdl.$EntityContainer) { - delete openapi.servers; - delete openapi.tags; - } - - security(openapi, entityContainer); - - return openapi; - - - /** - * Collect model info for easier lookup - * @param {object} csdl CSDL document - * @param {object} boundOverloads Map of action/function names to bound overloads - * @param {object} derivedTypes Map of type names to derived types - * @param {object} alias Map of namespace or alias to alias - * @param {object} namespace Map of namespace or alias to namespace - * @param {object} namespaceUrl Map of namespace to reference URL - * @param {object} voc Map of vocabularies and terms - */ - function preProcess(csdl, boundOverloads, derivedTypes, alias, namespace, namespaceUrl, voc) { - Object.keys(csdl.$Reference || {}).forEach(url => { - const reference = csdl.$Reference[url]; - (reference.$Include || []).forEach(include => { - const qualifier = include.$Alias || include.$Namespace; - alias[include.$Namespace] = qualifier; - namespace[qualifier] = include.$Namespace; - namespace[include.$Namespace] = include.$Namespace; - namespaceUrl[include.$Namespace] = url; - }); - }); - - getVocabularies(voc, alias); - - Object.keys(csdl).filter(name => isIdentifier(name)).forEach(name => { - const schema = csdl[name]; - const qualifier = schema.$Alias || name; - const isDefaultNamespace = schema[voc.Core.DefaultNamespace]; - - alias[name] = qualifier; - namespace[qualifier] = name; - namespace[name] = name; - - Object.keys(schema).filter(iName => isIdentifier(iName)).forEach(iName2 => { - const qualifiedName = qualifier + '.' + iName2; - const element = schema[iName2]; - if (Array.isArray(element)) { - element.filter(overload => overload.$IsBound).forEach(overload => { - const type = overload.$Parameter[0].$Type + (overload.$Parameter[0].$Collection ? '-c' : ''); - if (!boundOverloads[type]) boundOverloads[type] = []; - boundOverloads[type].push({ name: (isDefaultNamespace ? iName2 : qualifiedName), overload: overload }); - }); - } else if (element.$BaseType) { - const base = namespaceQualifiedName(element.$BaseType); - if (!derivedTypes[base]) derivedTypes[base] = []; - derivedTypes[base].push(qualifiedName); - } - }); - - Object.keys(schema.$Annotations || {}).forEach(target => { - const annotations = schema.$Annotations[target]; - const segments = target.split('/'); - const open = segments[0].indexOf('('); - let element; - if (open == -1) { - element = modelElement(segments[0]); - } else { - element = modelElement(segments[0].substring(0, open)); - let args = segments[0].substring(open + 1, segments[0].length - 1); - element = element.find( - (overload) => - (overload.$Kind == "Action" && - overload.$IsBound != true && - args == "") || - (overload.$Kind == "Action" && - args == - (overload.$Parameter[0].$Collection - ? `Collection(${overload.$Parameter[0].$Type})` - : overload.$Parameter[0].$Type || "")) || - (overload.$Parameter || []) - .map((p) => { - const type = p.$Type || "Edm.String"; - return p.$Collection ? `Collection(${type})` : type; - }) - .join(",") == args - ); - } - if (!element) { - DEBUG?.(`Invalid annotation target '${target}'`); - } else if (Array.isArray(element)) { - //TODO: action or function: - //- loop over all overloads - //- if there are more segments, a parameter or the return type is targeted - } else { - switch (segments.length) { - case 1: - Object.assign(element, annotations); - break; - case 2: - if (['Action', 'Function'].includes(element.$Kind)) { - if (segments[1] == '$ReturnType') { - if (element.$ReturnType) - Object.assign(element.$ReturnType, annotations); - } else { - const parameter = element.$Parameter.find(p => p.$Name == segments[1]); - Object.assign(parameter, annotations); - } - } else { - if (element[segments[1]]) { - Object.assign(element[segments[1]], annotations); - } else { - // DEBUG?.(`Invalid annotation target '${target}'`) - } - } - break; - default: - DEBUG?.('More than two annotation target path segments'); - } - } - }); - }); - } - - /** - * Construct map of qualified term names - * @param {object} voc Map of vocabularies and terms - * @param {object} alias Map of namespace or alias to alias - */ - function getVocabularies(voc, alias) { - const terms = { - Authorization: ['Authorizations', 'SecuritySchemes'], - Capabilities: ['BatchSupport', 'BatchSupported', 'ChangeTracking', 'CountRestrictions', 'DeleteRestrictions', 'DeepUpdateSupport', 'ExpandRestrictions', - 'FilterRestrictions', 'IndexableByKey', 'InsertRestrictions', 'KeyAsSegmentSupported', 'NavigationRestrictions', 'OperationRestrictions', - 'ReadRestrictions', 'SearchRestrictions', 'SelectSupport', 'SkipSupported', 'SortRestrictions', 'TopSupported', 'UpdateRestrictions'], - Core: ['AcceptableMediaTypes', 'Computed', 'ComputedDefaultValue', 'DefaultNamespace', 'Description', 'Example', 'Immutable', 'LongDescription', - 'OptionalParameter', 'Permissions', 'SchemaVersion'], - JSON: ['Schema'], - Validation: ['AllowedValues', 'Exclusive', 'Maximum', 'Minimum', 'Pattern'] - }; - - Object.keys(terms).forEach(vocab => { - voc[vocab] = {}; - terms[vocab].forEach(term => { - if (alias['Org.OData.' + vocab + '.V1'] != undefined) - voc[vocab][term] = '@' + alias['Org.OData.' + vocab + '.V1'] + '.' + term; - }); - }); - - voc.Common = { - Label: `@${alias['com.sap.vocabularies.Common.v1']}.Label` - } - } - - /** - * Construct the Info Object - * @param {object} csdl CSDL document - * @param {object} entityContainer Entity Container object - * @return {object} Info Object - */ - function getInfo(csdl, entityContainer) { - const namespace = csdl.$EntityContainer ? nameParts(csdl.$EntityContainer).qualifier : null; - const containerSchema = csdl.$EntityContainer ? csdl[namespace] : {}; - let description; - if (entityContainer && entityContainer[voc.Core.LongDescription]) { - description = entityContainer[voc.Core.LongDescription]; - } - else if (containerSchema && containerSchema[voc.Core.LongDescription]) { - description = containerSchema[voc.Core.LongDescription]; - } - else { - description = "Use @Core.LongDescription: '...' on your CDS service to provide a meaningful description."; - } - description += (diagram ? getResourceDiagram(csdl, entityContainer) : ''); - let title; - if (entityContainer && entityContainer[voc.Common.Label]) { - title = entityContainer[voc.Common.Label]; - } - else { - title = "Use @title: '...' on your CDS service to provide a meaningful title."; - } - return { - title: title, - description: csdl.$EntityContainer ? description : '', - version: containerSchema[voc.Core.SchemaVersion] || '' - }; - } - - /** - * Construct the externalDocs Object - * @param {object} csdl CSDL document - * @return {object} externalDocs Object - */ - function getExternalDoc(csdl) { - const namespace = csdl.$EntityContainer ? nameParts(csdl.$EntityContainer).qualifier : null; - const containerSchema = csdl.$EntityContainer ? csdl[namespace] : {}; - let externalDocs = {}; - if (containerSchema?.['@OpenAPI.externalDocs.description']) { - externalDocs.description = containerSchema['@OpenAPI.externalDocs.description']; - } - if (containerSchema?.['@OpenAPI.externalDocs.url']) { - externalDocs.url = containerSchema['@OpenAPI.externalDocs.url']; - } - return externalDocs; - } - - /** - * Construct resource diagram using web service at https://yuml.me - * @param {object} csdl CSDL document - * @param {object} entityContainer Entity Container object - * @return {string} resource diagram - */ - function getResourceDiagram(csdl, entityContainer) { - let diagram = ''; - let comma = ''; - //TODO: make colors configurable - let color = { resource: '{bg:lawngreen}', entityType: '{bg:lightslategray}', complexType: '', external: '{bg:whitesmoke}' } - - Object.keys(csdl).filter(name => isIdentifier(name)).forEach(namespace => { - const schema = csdl[namespace]; - Object.keys(schema).filter(name => isIdentifier(name) && ['EntityType', 'ComplexType'].includes(schema[name].$Kind)) - .forEach(typeName => { - const type = schema[typeName]; - diagram += comma - + (type.$BaseType ? '[' + nameParts(type.$BaseType).name + ']^' : '') - + '[' + typeName + (type.$Kind == 'EntityType' ? color.entityType : color.complexType) + ']'; - Object.keys(type).filter(name => isIdentifier(name)).forEach(propertyName => { - const property = type[propertyName]; - const targetNP = nameParts(property.$Type || 'Edm.String'); - if (property.$Kind == 'NavigationProperty' || targetNP.qualifier != 'Edm') { - const target = modelElement(property.$Type); - const bidirectional = property.$Partner && target && target[property.$Partner] && target[property.$Partner].$Partner == propertyName; - // Note: if the partner has the same name then it will also be depicted - if (!bidirectional || propertyName <= property.$Partner) { - diagram += ',[' + typeName + ']' - + ((property.$Kind != 'NavigationProperty' || property.$ContainsTarget) ? '++' : (bidirectional ? cardinality(target[property.$Partner]) : '')) - + '-' - + cardinality(property) - + ((property.$Kind != 'NavigationProperty' || bidirectional) ? '' : '>') - + '[' - + (target ? targetNP.name : property.$Type + color.external) - + ']'; - } - } - }); - comma = ','; - }); - }); - - Object.keys(entityContainer).filter(name => isIdentifier(name)).reverse().forEach(name => { - const resource = entityContainer[name]; - if (resource.$Type) { - diagram += comma - + '[' + name + '%20' + color.resource + ']' // additional space in case entity set and type have same name - + '++-' - + cardinality(resource) - + '>[' + nameParts(resource.$Type).name + ']'; - } else { - if (resource.$Action) { - diagram += comma - + '[' + name + color.resource + ']'; - const overload = modelElement(resource.$Action).find(pOverload => !pOverload.$IsBound); - diagram += overloadDiagram(name, overload); - } else if (resource.$Function) { - diagram += comma - + '[' + name + color.resource + ']'; - const overloads = modelElement(resource.$Function); - if (overloads) { - const unbound = overloads.filter(overload => !overload.$IsBound); - // TODO: loop over all overloads, add new source box after first arrow - diagram += overloadDiagram(name, unbound[0]); - } - } - } - }); - - if (diagram != '') { - diagram = '\n\n## Entity Data Model\n![ER Diagram](https://yuml.me/diagram/class/' - + diagram - + ')\n\n### Legend\n![Legend](https://yuml.me/diagram/plain;dir:TB;scale:60/class/[External.Type' + color.external - + '],[ComplexType' + color.complexType + '],[EntityType' + color.entityType - + '],[EntitySet/Singleton/Operation' + color.resource + '])'; - } - - return diagram; - - /** - * Diagram representation of property cardinality - * @param {object} typedElement Typed model element, e.g. property - * @return {string} cardinality - */ - function cardinality(typedElement) { - return typedElement.$Collection ? '*' : (typedElement.$Nullable ? '0..1' : ''); - } - - /** - * Diagram representation of action or function overload - * @param {string} name Name of action or function import - * @param {object} overload Action or function overload - * @return {string} diagram part - */ - function overloadDiagram(name, overload) { - let diag = ""; - if (overload.$ReturnType) { - const type = modelElement(overload.$ReturnType.$Type || "Edm.String"); - if (type) { - diag += "-" + cardinality(overload.$ReturnType) + ">[" + nameParts(overload.$ReturnType.$Type).name + "]"; - } - } - for (const param of overload.$Parameter || []) { - const type = modelElement(param.$Type || "Edm.String"); - if (type) { - diag += comma + "[" + name + color.resource + "]in-" + cardinality(param.$Type) + ">[" + nameParts(param.$Type).name + "]"; - } - } - return diag; - } - } - - /** - * Find model element by qualified name - * @param {string} qname Qualified name of model element - * @return {object} Model element - */ - function modelElement(qname) { - const q = nameParts(qname); - const schema = csdl[q.qualifier] || csdl[namespace[q.qualifier]]; - return schema ? schema[q.name] : null; - } - - /** - * Construct the short text - * @param {object} csdl CSDL document - * @param {object} entityContainer Entity Container object - * @return {string} short text - */ - function getShortText(csdl, entityContainer) { - const namespace = csdl.$EntityContainer ? nameParts(csdl.$EntityContainer).qualifier : null; - const containerSchema = csdl.$EntityContainer ? csdl[namespace] : {}; - let shortText; - if (entityContainer && entityContainer[voc.Core.Description]) { - shortText = entityContainer[voc.Core.Description]; - } - else if (containerSchema && containerSchema[voc.Core.Description]) { - shortText = containerSchema[voc.Core.Description]; - } - else { - shortText = "Use @Core.Description: '...' on your CDS service to provide a meaningful short text."; - } - return shortText; - } - - /** - * Construct an array of Server Objects - * @param {object} serviceRoot The service root - * @param {object} serversObject Input servers object - * @return {Array} The list of servers - */ - function getServers(serviceRoot, serversObject) { - let servers; - if (serversObject) { - try { - servers = JSON.parse(serversObject); - } catch (err) { - throw new Error(`The input server object is invalid.`); - } - - if (!servers.length) { - throw new Error(`The input server object should be an array.`); - } - } else { - servers = [{ url: serviceRoot }]; - } - return servers; - } - - /** - * Construct an array of Tag Objects from the entity container - * @param {object} container The entity container - * @return {Array} The list of tags - */ - function getTags(container) { - const tags = new Map(); - // all entity sets and singletons - Object.keys(container) - .filter(name => isIdentifier(name) && container[name].$Type) - .forEach(child => { - const type = modelElement(container[child].$Type) || {}; - const tag = { - name: type[voc.Common.Label] || child - }; - const description = container[child][voc.Core.Description] || type[voc.Core.Description]; - if (description) tag.description = description; - tags.set(tag.name, tag); - }); - return Array.from(tags.values()).sort((pre, next) => pre.name.localeCompare(next.name)); - } - - /** - * Construct the Paths Object from the entity container - * @param {object} container Entity container - * @return {object} Paths Object - */ - function getPaths(container) { - const paths = {}; - const resources = Object.keys(container).filter(name => isIdentifier(name)); - resources.forEach(name => { - let child = container[name]; - if (child.$Type) { - const type = modelElement(child.$Type); - const sourceName = (type && type[voc.Common.Label]) || name; - // entity sets and singletons are almost containment navigation properties - child.$ContainsTarget = true; - pathItems(paths, '/' + name, [], child, child, sourceName, sourceName, child, 0, ''); - } else if (child.$Action) { - pathItemActionImport(paths, name, child); - } else if (child.$Function) { - pathItemFunctionImport(paths, name, child); - } else { - DEBUG?.('Unrecognized entity container child: ' + name); - } - }) - if (resources.length > 0) pathItemBatch(paths, container); - return Object.keys(paths).sort().reduce((p, c) => (p[c] = paths[c], p), {}); - } - - /** - * Add path and Path Item Object for a navigation segment - * @param {object} paths Paths Object to augment - * @param {string} prefix Prefix for path - * @param {Array} prefixParameters Parameter Objects for prefix - * @param {object} element Model element of navigation segment - * @param {object} root Root model element - * @param {string} sourceName Name of path source - * @param {string} targetName Name of path target - * @param {string} target Target container child of path - * @param {integer} level Number of navigation segments so far - * @param {string} navigationPath Path for finding navigation restrictions - */ - function pathItems(paths, prefix, prefixParameters, element, root, sourceName, targetName, target, level, navigationPath) { - const name = prefix.substring(prefix.lastIndexOf('/') + 1); - const type = modelElement(element.$Type); - const pathItem = {}; - const restrictions = navigationPropertyRestrictions(root, navigationPath); - const nonExpandable = nonExpandableProperties(root, navigationPath); - - paths[prefix] = pathItem; - if (prefixParameters.length > 0) pathItem.parameters = prefixParameters; - - operationRead(pathItem, element, name, sourceName, targetName, target, level, restrictions, false, nonExpandable); - if (!root['$cds.autoexpose'] && element.$Collection && (element.$ContainsTarget || level < 2 && target)) { - operationCreate(pathItem, element, name, sourceName, targetName, target, level, restrictions); - } - pathItemsForBoundOperations(paths, prefix, prefixParameters, element, sourceName); - - if (element.$ContainsTarget) { - if (element.$Collection) { - if (level < maxLevels) - pathItemsWithKey(paths, prefix, prefixParameters, element, root, sourceName, targetName, target, level, navigationPath, restrictions, nonExpandable); - } else { - if (!root['$cds.autoexpose']) { - operationUpdate(pathItem, element, name, sourceName, target, level, restrictions); - if (element.$Nullable) { - operationDelete(pathItem, element, name, sourceName, target, level, restrictions); - } - } - pathItemsForBoundOperations(paths, prefix, prefixParameters, element, sourceName); - pathItemsWithNavigation(paths, prefix, prefixParameters, type, root, sourceName, level, navigationPath); - } - } - - if (Object.keys(pathItem).filter((i) => i !== "parameters").length === 0) - delete paths[prefix]; - } - - /** - * Find navigation restrictions for a navigation path - * @param {object} root Root model element - * @param {string} navigationPath Path for finding navigation restrictions - * @return Navigation property restrictions of navigation segment - */ - function navigationPropertyRestrictions(root, navigationPath) { - const navigationRestrictions = root[voc.Capabilities.NavigationRestrictions] || {}; - return (navigationRestrictions.RestrictedProperties || []).find(item => navigationPropertyPath(item.NavigationProperty) == navigationPath) - || {}; - } - - /** - * Find non-expandable properties for a navigation path - * @param {object} root Root model element - * @param {string} navigationPath Path for finding navigation restrictions - * @return Navigation property restrictions of navigation segment - */ - function nonExpandableProperties(root, navigationPath) { - const expandRestrictions = root[voc.Capabilities.ExpandRestrictions] || {}; - const prefix = navigationPath.length === 0 ? '' : navigationPath + '/' - const from = prefix.length - const nonExpandable = [] - for (const path of (expandRestrictions.NonExpandableProperties || [])) { - if (path.startsWith(prefix)) { - nonExpandable.push(path.substring(from)) - } - } - return nonExpandable; - } - - /** - * Add path and Path Item Object for a navigation segment with key - * @param {object} paths Paths Object to augment - * @param {string} prefix Prefix for path - * @param {Array} prefixParameters Parameter Objects for prefix - * @param {object} element Model element of navigation segment - * @param {object} root Root model element - * @param {string} sourceName Name of path source - * @param {string} targetName Name of path target - * @param {string} target Target container child of path - * @param {integer} level Number of navigation segments so far - * @param {string} navigationPath Path for finding navigation restrictions - * @param {object} restrictions Navigation property restrictions of navigation segment - * @param {array} nonExpandable Non-expandable navigation properties - */ - function pathItemsWithKey(paths, prefix, prefixParameters, element, root, sourceName, targetName, target, level, navigationPath, restrictions, nonExpandable) { - const targetIndexable = target == null || target[voc.Capabilities.IndexableByKey] != false; - if (restrictions.IndexableByKey == true || restrictions.IndexableByKey != false && targetIndexable) { - const name = prefix.substring(prefix.lastIndexOf('/') + 1); - const type = modelElement(element.$Type); - const key = entityKey(type, level); - if (key.parameters.length > 0) { - const path = prefix + key.segment; - const parameters = prefixParameters.concat(key.parameters); - const pathItem = { parameters: parameters }; - paths[path] = pathItem; - - operationRead(pathItem, element, name, sourceName, targetName, target, level, restrictions, true, nonExpandable); - if (!root['$cds.autoexpose']) { - operationUpdate(pathItem, element, name, sourceName, target, level, restrictions, true); - operationDelete(pathItem, element, name, sourceName, target, level, restrictions, true); - } - if (Object.keys(pathItem).filter((i) => i !== "parameters").length === 0) - delete paths[path]; - - pathItemsForBoundOperations(paths, path, parameters, element, sourceName, true); - pathItemsWithNavigation(paths, path, parameters, type, root, sourceName, level, navigationPath); - } - } - } - - /** - * Construct Operation Object for create - * @param {object} pathItem Path Item Object to augment - * @param {object} element Model element of navigation segment - * @param {string} name Name of navigation segment - * @param {string} sourceName Name of path source - * @param {string} targetName Name of path target - * @param {string} target Target container child of path - * @param {integer} level Number of navigation segments so far - * @param {object} restrictions Navigation property restrictions of navigation segment - */ - function operationCreate(pathItem, element, name, sourceName, targetName, target, level, restrictions) { - const insertRestrictions = restrictions.InsertRestrictions || target && target[voc.Capabilities.InsertRestrictions] || {}; - let countRestrictions = target && (target[voc.Capabilities.CountRestrictions]?.Countable === false); // count property will be added if CountRestrictions is false - if (insertRestrictions.Insertable !== false) { - const lname = pluralize.singular(splitName(name)); - const type = modelElement(element.$Type); - pathItem.post = { - summary: insertRestrictions.Description || operationSummary('Creates', name, sourceName, level, true, true), - tags: [sourceName], - requestBody: { - description: type && type[voc.Core.Description] || 'New ' + lname, - required: true, - content: { - 'application/json': { - schema: ref(element.$Type, SUFFIX.create), - } - } - }, - responses: response(201, 'Created ' + lname, { $Type: element.$Type }, insertRestrictions.ErrorResponses, !countRestrictions), - }; - if (insertRestrictions.LongDescription) pathItem.post.description = insertRestrictions.LongDescription; - if (targetName && sourceName != targetName) pathItem.post.tags.push(targetName); - customParameters(pathItem.post, insertRestrictions); - } - } - - /** - * Split camel-cased name into words - * @param {string} name Name to split - * @return {string} Split name - */ - function splitName(name) { - return name.split(/(?=[A-Z])/g).join(' ').toLowerCase().replace(/ i d/g, ' id'); - } - - /** - * Construct operation summary - * @param {string} operation Operation (verb) - * @param {string} name Name of navigation segment - * @param {string} sourceName Name of path source - * @param {integer} level Number of navigation segments so far - * @param {boolean} collection Access a collection - * @param {boolean} byKey Access by key - * @return {string} Operation Text - */ - function operationSummary(operation, name, sourceName, level, collection, byKey) { - let lname = splitName(name); - let sname = splitName(sourceName); - - return operation + ' ' - + (byKey ? 'a single ' : (collection ? 'a list of ' : '')) - + (byKey ? pluralize.singular(lname) : lname) - //TODO: suppress "a" for all singletons - + (level == 0 ? '' : (level == 1 && sname == 'me' ? ' of me' : ' of a ' + pluralize.singular(sname))) - + '.' - } - - /** - * Construct Operation Object for read - * @param {object} pathItem Path Item Object to augment - * @param {object} element Model element of navigation segment - * @param {string} name Name of navigation segment - * @param {string} sourceName Name of path source - * @param {string} targetName Name of path target - * @param {string} target Target container child of path - * @param {integer} level Number of navigation segments so far - * @param {object} restrictions Navigation property restrictions of navigation segment - * @param {boolean} byKey Read by key - * @param {array} nonExpandable Non-expandable navigation properties - */ - function operationRead(pathItem, element, name, sourceName, targetName, target, level, restrictions, byKey, nonExpandable) { - const targetRestrictions = target?.[voc.Capabilities.ReadRestrictions]; - const readRestrictions = restrictions.ReadRestrictions || targetRestrictions || {}; - const readByKeyRestrictions = readRestrictions.ReadByKeyRestrictions; - let readable = true; - let countRestrictions = target && (target[voc.Capabilities.CountRestrictions]?.Countable === false); - if (byKey && readByKeyRestrictions && readByKeyRestrictions.Readable !== undefined) - readable = readByKeyRestrictions.Readable; - else if (readRestrictions.Readable !== undefined) - readable = readRestrictions.Readable; - - if (readable) { - let descriptions = (level == 0 ? targetRestrictions : restrictions.ReadRestrictions) || {}; - if (byKey) descriptions = descriptions.ReadByKeyRestrictions || {}; - const lname = splitName(name); - const collection = !byKey && element.$Collection; - const operation = { - summary: descriptions.Description || operationSummary('Retrieves', name, sourceName, level, element.$Collection, byKey), - tags: [sourceName], - parameters: [], - responses: response(200, 'Retrieved ' + (byKey ? pluralize.singular(lname) : lname), { $Type: element.$Type, $Collection: collection }, - byKey ? readByKeyRestrictions?.ErrorResponses : readRestrictions?.ErrorResponses, !countRestrictions) - }; - const deltaSupported = element[voc.Capabilities.ChangeTracking] && element[voc.Capabilities.ChangeTracking].Supported; - if (!byKey && deltaSupported) { - operation.responses[200].content['application/json'].schema.properties['@odata.deltaLink'] = { - type: 'string', - example: basePath + '/' + name + '?$deltatoken=opaque server-generated token for fetching the delta' - } - } - if (descriptions.LongDescription) operation.description = descriptions.LongDescription; - if (target && sourceName != targetName) operation.tags.push(targetName); - customParameters(operation, byKey ? readByKeyRestrictions || readRestrictions : readRestrictions); - - if (collection) { - optionTop(operation.parameters, target, restrictions); - optionSkip(operation.parameters, target, restrictions); - if (csdl.$Version >= '4.0') optionSearch(operation.parameters, target, restrictions); - optionFilter(operation.parameters, target, restrictions); - optionCount(operation.parameters, target); - optionOrderBy(operation.parameters, element, target, restrictions); - } - - optionSelect(operation.parameters, element, target, restrictions); - optionExpand(operation.parameters, element, target, nonExpandable); - - pathItem.get = operation; - } - } - - /** - * Add custom headers and query options - * @param {object} operation Operation object to augment - * @param {object} restrictions Restrictions for operation - */ - function customParameters(operation, restrictions) { - if ( - !operation.parameters && - (restrictions.CustomHeaders || restrictions.CustomQueryOptions) - ) - operation.parameters = []; - for (const custom of restrictions.CustomHeaders || []) { - operation.parameters.push(customParameter(custom, "header")); - } - - for (const custom of restrictions.CustomQueryOptions || []) { - operation.parameters.push(customParameter(custom, "query")); - } - } - - /** - * Construct custom parameter - * @param {object} custom custom parameter in OData format - * @param {string} location "header" or "query" - */ - function customParameter(custom, location) { - return { - name: custom.Name, - in: location, - required: custom.Required || false, - ...(custom.Description && { description: custom.Description }), - schema: { - type: "string", - ...(custom.DocumentationURL && { - externalDocs: { url: custom.DocumentationURL }, - }), - //TODO: Examples - }, - }; - } - - /** - * Add parameter for query option $count - * @param {Array} parameters Array of parameters to augment - * @param {string} target Target container child of path - */ - function optionCount(parameters, target) { - const targetRestrictions = target && target[voc.Capabilities.CountRestrictions]; - const targetCountable = target == null - || targetRestrictions == null - || targetRestrictions.Countable !== false; - - if (targetCountable) { - parameters.push({ - - $ref: '#/components/parameters/count' - }); - } - } - - /** - * Add parameter for query option $expand - * @param {Array} parameters Array of parameters to augment - * @param {object} element Model element of navigation segment - * @param {string} target Target container child of path - * @param {array} nonExpandable Non-expandable navigation properties - */ - function optionExpand(parameters, element, target, nonExpandable) { - const targetRestrictions = target && target[voc.Capabilities.ExpandRestrictions]; - const supported = targetRestrictions == null || targetRestrictions.Expandable != false; - if (supported) { - const expandItems = ['*'].concat(navigationPaths(element).filter(path => !nonExpandable.includes(path))); - if (expandItems.length > 1) { - parameters.push({ - name: queryOptionPrefix + 'expand', - description: (targetRestrictions && targetRestrictions[voc.Core.Description]) - || 'The value of $expand query option is a comma-separated list of navigation property names, \ -stream property names, or $value indicating the stream content of a media-entity. \ -The corresponding related entities and stream values will be represented inline, \ -see [Expand](http://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part1-protocol.html#sec_SystemQueryOptionexpand)', - in: 'query', - explode: false, - schema: { - type: 'array', - uniqueItems: true, - items: { - type: 'string', - enum: expandItems - } - } - }); - } - } - } - - /** - * Collect navigation paths of a navigation segment and its potentially structured components - * @param {object} element Model element of navigation segment - * @param {string} prefix Navigation prefix - * @param {integer} level Number of navigation segments so far - * @return {Array} Array of navigation property paths - */ - function navigationPaths(element, prefix = '', level = 0) { - const paths = []; - const type = modelElement(element.$Type); - const properties = propertiesOfStructuredType(type); - Object.keys(properties).forEach(key => { - if (properties[key].$Kind == 'NavigationProperty') { - paths.push(prefix + key) - } else if (properties[key].$Type && level < maxLevels) { - paths.push(...navigationPaths(properties[key], prefix + key + '/', level + 1)); - } - }) - return paths; - } - - /** - * Add parameter for query option $filter - * @param {Array} parameters Array of parameters to augment - * @param {string} target Target container child of path - * @param {object} restrictions Navigation property restrictions of navigation segment - */ - function optionFilter(parameters, target, restrictions) { - const filterRestrictions = restrictions.FilterRestrictions || target && target[voc.Capabilities.FilterRestrictions] || {}; - - if (filterRestrictions.Filterable !== false) { - const filter = { - name: queryOptionPrefix + 'filter', - description: filterRestrictions[voc.Core.Description] - || 'Filter items by property values, see [Filtering](http://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part1-protocol.html#sec_SystemQueryOptionfilter)', - in: 'query', - schema: { - type: 'string' - } - }; - if (filterRestrictions.RequiresFilter) - filter.required = true; - if (filterRestrictions.RequiredProperties) { - filter.description += '\n\nRequired filter properties:'; - filterRestrictions.RequiredProperties.forEach( - item => filter.description += '\n- ' + propertyPath(item) - ); - } - parameters.push(filter); - } - } - - /** - * Add parameter for query option $orderby - * @param {Array} parameters Array of parameters to augment - * @param {object} element Model element of navigation segment - * @param {string} target Target container child of path - * @param {object} restrictions Navigation property restrictions of navigation segment - */ - function optionOrderBy(parameters, element, target, restrictions) { - const sortRestrictions = restrictions.SortRestrictions || target && target[voc.Capabilities.SortRestrictions] || {}; - - if (sortRestrictions.Sortable !== false) { - const nonSortable = {}; - (sortRestrictions.NonSortableProperties || []).forEach(name => { - nonSortable[propertyPath(name)] = true; - }); - const orderbyItems = []; - primitivePaths(element).filter(property => !nonSortable[property]).forEach(property => { - orderbyItems.push(property); - orderbyItems.push(property + ' desc'); - }); - if (orderbyItems.length > 0) { - parameters.push({ - name: queryOptionPrefix + 'orderby', - description: sortRestrictions[voc.Core.Description] - || 'Order items by property values, see [Sorting](http://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part1-protocol.html#sec_SystemQueryOptionorderby)', - in: 'query', - explode: false, - schema: { - type: 'array', - uniqueItems: true, - items: { - type: 'string', - enum: orderbyItems - } - } - }); - } - } - } - - /** - * Unpack EnumMember value if it uses CSDL JSON CS01 style, like CAP does - * @param {string or object} path Qualified name of referenced type - * @return {object} Reference Object - */ - function enumMember(member) { - if (typeof member == 'string') - return member; - else if (typeof member == 'object') - return member.$EnumMember; - } - - /** - * Unpack NavigationPropertyPath value if it uses CSDL JSON CS01 style, like CAP does - * @param {string or object} path Qualified name of referenced type - * @return {object} Reference Object - */ - function navigationPropertyPath(path) { - if (typeof path == 'string') - return path; - else - return path.$NavigationPropertyPath; - } - - /** - * Unpack PropertyPath value if it uses CSDL JSON CS01 style, like CAP does - * @param {string or object} path Qualified name of referenced type - * @return {object} Reference Object - */ - function propertyPath(path) { - if (typeof path == 'string') - return path; - else - return path.$PropertyPath; - } - - /** - * Collect primitive paths of a navigation segment and its potentially structured components - * @param {object} element Model element of navigation segment - * @param {string} prefix Navigation prefix - * @return {Array} Array of primitive property paths - */ - function primitivePaths(element, prefix = '') { - const paths = []; - const elementType = modelElement(element.$Type); - - if (!elementType) { - DEBUG?.(`Unknown type for element: ${JSON.stringify(element)}`); - return paths; - } - - const propsOfType = propertiesOfStructuredType(elementType); - const ignore = Object.entries(propsOfType) - .filter(entry => entry[1].$Kind !== 'NavigationProperty') - .filter(entry => entry[1].$Type) - .filter(entry => nameParts(entry[1].$Type).qualifier !== 'Edm') - .filter(entry => !modelElement(entry[1].$Type)); - - // Keep old logging - ignore.forEach(entry => DEBUG?.(`Unknown type for element: ${JSON.stringify(entry)}`)); - - const properties = Object.entries(propsOfType) - .filter(entry => entry[1].$Kind !== 'NavigationProperty') - .filter(entry => !ignore.includes(entry)) - .map(entryToProperty({ path: prefix, typeRefChain: [] })); - - for (let i = 0; i < properties.length; i++) { - const property = properties[i]; - if (!property.isComplex) { - paths.push(property.path); - continue; - } - - const typeRefChainTail = property.typeRefChain[property.typeRefChain.length - 1]; - - // Allow full cycle to be shown (0) times - if (property.typeRefChain.filter(_type => _type === typeRefChainTail).length > 1) { - DEBUG?.(`Cycle detected ${property.typeRefChain.join('->')}`); - continue; - } - - const expanded = Object.entries(property.properties) - .filter(pProperty => pProperty[1].$Kind !== 'NavigationProperty') - .map(entryToProperty(property)) - properties.splice(i + 1, 0, ...expanded); - } - - return paths; - } - - function entryToProperty(parent) { - - return function (entry) { - const key = entry[0]; - const property = entry[1]; - const propertyType = property.$Type && modelElement(property.$Type); - - if (propertyType && propertyType.$Kind && propertyType.$Kind === 'ComplexType') { - return { - properties: propertiesOfStructuredType(propertyType), - path: `${parent.path}${key}/`, - typeRefChain: parent.typeRefChain.concat(property.$Type), - isComplex: true - } - } - - return { - properties: {}, - path: `${parent.path}${key}`, - typeRefChain: [], - isComplex: false, - } - }; - } - - /** - * Add parameter for query option $search - * @param {Array} parameters Array of parameters to augment - * @param {string} target Target container child of path - * @param {object} restrictions Navigation property restrictions of navigation segment - */ - function optionSearch(parameters, target, restrictions) { - const searchRestrictions = restrictions.SearchRestrictions || target && target[voc.Capabilities.SearchRestrictions] || {}; - - if (searchRestrictions.Searchable !== false) { - if (searchRestrictions[voc.Core.Description]) { - parameters.push({ - name: queryOptionPrefix + 'search', - description: searchRestrictions[voc.Core.Description], - in: 'query', - schema: { type: 'string' } - }); - } else { - parameters.push({ $ref: '#/components/parameters/search' }); - } - } - } - - /** - * Add parameter for query option $select - * @param {Array} parameters Array of parameters to augment - * @param {object} element Model element of navigation segment - * @param {string} target Target container child of path - * @param {object} restrictions Navigation property restrictions of navigation segment - */ - function optionSelect(parameters, element, target, restrictions) { - const selectSupport = restrictions.SelectSupport || target && target[voc.Capabilities.SelectSupport] || {}; - - if (selectSupport.Supported !== false) { - const type = modelElement(element.$Type) || {}; - const properties = propertiesOfStructuredType(type); - const selectItems = []; - Object.keys(properties).filter(key => properties[key].$Kind != 'NavigationProperty').forEach( - key => selectItems.push(key) - ) - if (selectItems.length > 0) { - parameters.push({ - name: queryOptionPrefix + 'select', - description: 'Select properties to be returned, see [Select](http://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part1-protocol.html#sec_SystemQueryOptionselect)', - in: 'query', - explode: false, - schema: { - type: 'array', - uniqueItems: true, - items: { - type: 'string', - enum: selectItems - } - } - }); - } - } - } - - /** - * Add parameter for query option $skip - * @param {Array} parameters Array of parameters to augment - * @param {string} target Target container child of path - * @param {object} restrictions Navigation property restrictions of navigation segment - */ - function optionSkip(parameters, target, restrictions) { - const supported = restrictions.SkipSupported !== undefined - ? restrictions.SkipSupported - : target == null || target[voc.Capabilities.SkipSupported] !== false; - - if (supported) { - parameters.push({ - $ref: '#/components/parameters/skip' - }); - } - } - - /** - * Add parameter for query option $top - * @param {Array} parameters Array of parameters to augment - * @param {string} target Target container child of path - * @param {object} restrictions Navigation property restrictions of navigation segment - */ - function optionTop(parameters, target, restrictions) { - const supported = restrictions.TopSupported !== undefined - ? restrictions.TopSupported - : target == null || target[voc.Capabilities.TopSupported] !== false; - - if (supported) { - parameters.push({ - $ref: '#/components/parameters/top' - }); - } - } - - /** - * Construct Operation Object for update - * @param {object} pathItem Path Item Object to augment - * @param {object} element Model element of navigation segment - * @param {string} name Name of navigation segment - * @param {string} sourceName Name of path source - * @param {string} target Target container child of path - * @param {integer} level Number of navigation segments so far - * @param {object} restrictions Navigation property restrictions of navigation segment - * @param {boolean} byKey Update by key - */ - function operationUpdate(pathItem, element, name, sourceName, target, level, restrictions, byKey) { - const updateRestrictions = restrictions.UpdateRestrictions || target && target[voc.Capabilities.UpdateRestrictions] || {}; - let countRestrictions = target && (target[voc.Capabilities.CountRestrictions]?.Countable === false); - if (updateRestrictions.Updatable !== false) { - const type = modelElement(element.$Type); - const operation = { - summary: updateRestrictions.Description || operationSummary('Changes', name, sourceName, level, element.$Collection, byKey), - tags: [sourceName], - requestBody: { - description: type && type[voc.Core.Description] || 'New property values', - required: true, - content: { - 'application/json': { - schema: ref(element.$Type, SUFFIX.update), - } - } - }, - responses: response(204, "Success", undefined, updateRestrictions.ErrorResponses, !countRestrictions), - }; - if (updateRestrictions.LongDescription) operation.description = updateRestrictions.LongDescription; - customParameters(operation, updateRestrictions); - const updateMethod = updateRestrictions.UpdateMethod ? updateRestrictions.UpdateMethod.toLowerCase() : "patch"; - pathItem[updateMethod] = operation; - } - } - - /** - * Construct Operation Object for delete - * @param {object} pathItem Path Item Object to augment - * @param {object} element Model element of navigation segment - * @param {string} name Name of navigation segment - * @param {string} sourceName Name of path source - * @param {string} target Target container child of path - * @param {integer} level Number of navigation segments so far - * @param {object} restrictions Navigation property restrictions of navigation segment - * @param {boolean} byKey Delete by key - */ - function operationDelete(pathItem, element, name, sourceName, target, level, restrictions, byKey) { - const deleteRestrictions = restrictions.DeleteRestrictions || target && target[voc.Capabilities.DeleteRestrictions] || {}; - let countRestrictions = target && (target[voc.Capabilities.CountRestrictions]?.Countable === false); - if (deleteRestrictions.Deletable !== false) { - pathItem.delete = { - summary: deleteRestrictions.Description || operationSummary('Deletes', name, sourceName, level, element.$Collection, byKey), - tags: [sourceName], - responses: response(204, "Success", undefined, deleteRestrictions.ErrorResponses, !countRestrictions), - }; - if (deleteRestrictions.LongDescription) pathItem.delete.description = deleteRestrictions.LongDescription; - customParameters(pathItem.delete, deleteRestrictions); - } - } - - /** - * Add paths and Path Item Objects for navigation segments - * @param {object} paths The Paths Object to augment - * @param {string} prefix Prefix for path - * @param {Array} prefixParameters Parameter Objects for prefix - * @param {object} type Entity type object of navigation segment - * @param {string} sourceName Name of path source - * @param {integer} level Number of navigation segments so far - * @param {string} navigationPrefix Path for finding navigation restrictions - */ - function pathItemsWithNavigation(paths, prefix, prefixParameters, type, root, sourceName, level, navigationPrefix) { - const navigationRestrictions = root[voc.Capabilities.NavigationRestrictions] || {}; - const rootNavigable = level == 0 && enumMember(navigationRestrictions.Navigability) != 'None' - || level == 1 && enumMember(navigationRestrictions.Navigability) != 'Single' - || level > 1; - - if (type && level < maxLevels) { - const properties = navigationPathMap(type); - Object.keys(properties).forEach(name => { - const parentRestrictions = navigationPropertyRestrictions(root, navigationPrefix); - if (enumMember(parentRestrictions.Navigability) == 'Single') return; - - const navigationPath = navigationPrefix + (navigationPrefix.length > 0 ? '/' : '') + name; - const restrictions = navigationPropertyRestrictions(root, navigationPath); - if (['Recursive', 'Single'].includes(enumMember(restrictions.Navigability)) - || restrictions.Navigability == null && rootNavigable) { - const targetSetName = root.$NavigationPropertyBinding && root.$NavigationPropertyBinding[navigationPath]; - const target = entityContainer[targetSetName]; - const targetType = target && modelElement(target.$Type); - const targetName = (targetType && targetType[voc.Common.Label]) || targetSetName; - pathItems(paths, prefix + '/' + name, prefixParameters, properties[name], root, sourceName, targetName, target, level + 1, navigationPath); - } - }); - } - } - - /** - * Collect navigation paths of a navigation segment and its potentially structured components - * @param {object} type Structured type - * @param {object} map Map of navigation property paths and their types - * @param {string} prefix Navigation prefix - * @param {integer} level Number of navigation segments so far - * @return {object} Map of navigation property paths and their types - */ - function navigationPathMap(type, map = {}, prefix = '', level = 0) { - const properties = propertiesOfStructuredType(type); - Object.keys(properties).forEach(key => { - if (properties[key].$Kind == 'NavigationProperty') { - map[prefix + key] = properties[key]; - } else if (properties[key].$Type && !properties[key].$Collection && level < maxLevels) { - navigationPathMap(modelElement(properties[key].$Type), map, prefix + key + '/', level + 1); - } - }) - return map; - } - - /** - * Construct map of key names for an entity type - * @param {object} type Entity type object - * @return {object} Map of key names - */ - function keyMap(type) { - const map = {}; - if (type.$Kind == 'EntityType') { - const keys = getKey(type) || []; - keys.forEach(key => { - if (typeof key == 'string') - map[key] = true; - }); - } - return map; - } - - /** - * Key for path item - * @param {object} entityType Entity Type object - * @return {array} Key of entity type or null - */ - function getKey(entityType) { - let type = entityType; - let keys = null; - while (type) { - keys = type.$Key; - if (keys || !type.$BaseType) break; - type = modelElement(type.$BaseType); - } - return keys; - } - - /** - * Key for path item - * @param {object} entityType Entity Type object - * @param {integer} level Number of navigation segments so far - * @return {object} key: Key segment, parameters: key parameters - */ - function entityKey(entityType, level) { - let segment = ''; - const params = []; - const keys = getKey(entityType) || []; - const properties = propertiesOfStructuredType(entityType); - - keys.forEach((key, index) => { - const suffix = level > 0 ? '_' + level : ''; - if (keyAsSegment) - segment += '/'; - else { - if (index > 0) segment += ','; - if (keys.length != 1) segment += key + '='; - } - let parameter; - let property = {}; - if (typeof key == 'string') { - parameter = key; - property = properties[key]; - } else { - parameter = Object.keys(key)[0]; - const segments = key[parameter].split('/'); - property = properties[segments[0]]; - for (let i = 1; i < segments.length; i++) { - const complexType = modelElement(property.$Type); - const properties = propertiesOfStructuredType(complexType); - property = properties[segments[i]]; - } - } - const propertyType = property.$Type; - segment += pathValuePrefix(propertyType) + '{' + parameter + suffix + '}' + pathValueSuffix(propertyType); - const param = { - description: [property[voc.Core.Description], property[voc.Core.LongDescription]].filter(t => t).join(' \n') - || 'key: ' + parameter, - in: 'path', - name: parameter + suffix, - required: true, - schema: getSchema(property, '', true) - }; - params.push(param); - }) - return { segment: (keyAsSegment ? '' : '(') + segment + (keyAsSegment ? '' : ')'), parameters: params }; - } - - /** - * Prefix for key value in key segment - * @param {typename} Qualified name of key property type - * @return {string} value prefix - */ - function pathValuePrefix(typename) { - //TODO: handle other Edm types, enumeration types, and type definitions - if (['Edm.Int64', 'Edm.Int32', 'Edm.Int16', 'Edm.SByte', 'Edm.Byte', - 'Edm.Double', 'Edm.Single', 'Edm.Date', 'Edm.DateTimeOffset', 'Edm.Guid'].includes(typename)) return ''; - if (keyAsSegment) return ''; - return `'`; - } - - /** - * Suffix for key value in key segment - * @param {typename} Qualified name of key property type - * @return {string} value prefix - */ - function pathValueSuffix(typename) { - //TODO: handle other Edm types, enumeration types, and type definitions - if (['Edm.Int64', 'Edm.Int32', 'Edm.Int16', 'Edm.SByte', 'Edm.Byte', - 'Edm.Double', 'Edm.Single', 'Edm.Date', 'Edm.DateTimeOffset', 'Edm.Guid'].includes(typename)) return ''; - if (keyAsSegment) return ''; - return `'`; - } - /** * Add path and Path Item Object for actions and functions bound to the element * @param {object} paths Paths Object to augment diff --git a/lib/compile/modules/builders/index.js b/lib/compile/modules/builders/index.js new file mode 100644 index 0000000..19c9d9c --- /dev/null +++ b/lib/compile/modules/builders/index.js @@ -0,0 +1,15 @@ +/** + * Builder modules index + * + * Re-exports all builder modules for convenient access + */ + +const paths = require('./paths'); +const parameters = require('./parameters'); +const responses = require('./responses'); + +module.exports = { + ...paths, + ...parameters, + ...responses +}; \ No newline at end of file diff --git a/lib/compile/modules/builders/parameters.js b/lib/compile/modules/builders/parameters.js new file mode 100644 index 0000000..7a4ddc0 --- /dev/null +++ b/lib/compile/modules/builders/parameters.js @@ -0,0 +1,332 @@ +/** + * Parameter Building Module + * + * This module contains all functions related to building OpenAPI parameters + * from CDS model elements. + */ + +const { propertyPath, primitivePaths } = require('./paths'); +const { enumMember } = require('../utils/naming'); +const { Logger } = require('../utils/logger'); + +const logger = new Logger('csdl2openapi:parameters'); +const DEBUG = logger.debug.bind(logger); + +/** + * Add standard OData query parameters to a path + * @param {Array} parameters - Array of parameters to augment + * @param {object} element - Model element + * @param {object} modelElement - Function to get model element + * @param {object} propertiesOfStructuredType - Function to get properties + * @param {object} root - Root entity set + * @param {string} navigationPath - Navigation path for restrictions + * @param {object} target - Target container child + * @param {object} restrictions - Navigation restrictions + * @param {object} options - Options including queryOptionPrefix + */ +function addQueryOptions(parameters, element, modelElement, propertiesOfStructuredType, root, navigationPath, target, restrictions, options = {}) { + const { queryOptionPrefix = '$' } = options; + + // Add standard query options + optionTop(parameters, restrictions, queryOptionPrefix); + optionSkip(parameters, restrictions, queryOptionPrefix); + optionCount(parameters, restrictions, target, queryOptionPrefix); + optionFilter(parameters, element, modelElement, propertiesOfStructuredType, target, restrictions, queryOptionPrefix); + optionOrderBy(parameters, element, modelElement, propertiesOfStructuredType, target, restrictions, queryOptionPrefix); + optionSearch(parameters, target, restrictions, queryOptionPrefix); +} + +/** + * Add parameter for query option $top + * @param {Array} parameters - Array of parameters to augment + * @param {object} restrictions - Navigation property restrictions + * @param {string} queryOptionPrefix - Query option prefix + */ +function optionTop(parameters, restrictions, queryOptionPrefix = '$') { + if (restrictions.TopSupported !== false) { + parameters.push({ $ref: '#/components/parameters/top' }); + } +} + +/** + * Add parameter for query option $skip + * @param {Array} parameters - Array of parameters to augment + * @param {object} restrictions - Navigation property restrictions + * @param {string} queryOptionPrefix - Query option prefix + */ +function optionSkip(parameters, restrictions, queryOptionPrefix = '$') { + if (restrictions.SkipSupported !== false) { + parameters.push({ $ref: '#/components/parameters/skip' }); + } +} + +/** + * Add parameter for query option $count + * @param {Array} parameters - Array of parameters to augment + * @param {object} restrictions - Navigation property restrictions + * @param {string} target - Target container child + * @param {string} queryOptionPrefix - Query option prefix + */ +function optionCount(parameters, restrictions, target, queryOptionPrefix = '$') { + const countRestrictions = restrictions.CountRestrictions || (target && target['Org.OData.Capabilities.V1.CountRestrictions']) || {}; + + if (countRestrictions.Countable !== false) { + parameters.push({ $ref: '#/components/parameters/count' }); + } +} + +/** + * Add parameter for query option $filter + * @param {Array} parameters - Array of parameters to augment + * @param {object} element - Model element + * @param {Function} modelElement - Function to get model element + * @param {Function} propertiesOfStructuredType - Function to get properties + * @param {string} target - Target container child + * @param {object} restrictions - Navigation property restrictions + * @param {string} queryOptionPrefix - Query option prefix + */ +function optionFilter(parameters, element, modelElement, propertiesOfStructuredType, target, restrictions, queryOptionPrefix = '$') { + const filterRestrictions = restrictions.FilterRestrictions || (target && target['Org.OData.Capabilities.V1.FilterRestrictions']) || {}; + + if (filterRestrictions.Filterable !== false) { + const filter = { + name: queryOptionPrefix + 'filter', + description: filterRestrictions['Org.OData.Core.V1.Description'] + || 'Filter items by property values, see [Filtering](http://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part1-protocol.html#sec_SystemQueryOptionfilter)', + in: 'query', + schema: { + type: 'string' + } + }; + + if (filterRestrictions.RequiresFilter) + filter.required = true; + + if (filterRestrictions.RequiredProperties) { + filter.description += '\n\nRequired filter properties:'; + filterRestrictions.RequiredProperties.forEach( + item => filter.description += '\n- ' + propertyPath(item) + ); + } + + parameters.push(filter); + } +} + +/** + * Add parameter for query option $orderby + * @param {Array} parameters - Array of parameters to augment + * @param {object} element - Model element of navigation segment + * @param {Function} modelElement - Function to get model element + * @param {Function} propertiesOfStructuredType - Function to get properties + * @param {string} target - Target container child of path + * @param {object} restrictions - Navigation property restrictions of navigation segment + * @param {string} queryOptionPrefix - Query option prefix + */ +function optionOrderBy(parameters, element, modelElement, propertiesOfStructuredType, target, restrictions, queryOptionPrefix = '$') { + const sortRestrictions = restrictions.SortRestrictions || (target && target['Org.OData.Capabilities.V1.SortRestrictions']) || {}; + + if (sortRestrictions.Sortable !== false) { + const nonSortable = {}; + (sortRestrictions.NonSortableProperties || []).forEach(name => { + nonSortable[propertyPath(name)] = true; + }); + + const orderbyItems = []; + primitivePaths(element, modelElement, propertiesOfStructuredType).filter(property => !nonSortable[property]).forEach(property => { + orderbyItems.push(property); + orderbyItems.push(property + ' desc'); + }); + + if (orderbyItems.length > 0) { + parameters.push({ + name: queryOptionPrefix + 'orderby', + description: sortRestrictions['Org.OData.Core.V1.Description'] + || 'Order items by property values, see [Sorting](http://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part1-protocol.html#sec_SystemQueryOptionorderby)', + in: 'query', + explode: false, + schema: { + type: 'array', + uniqueItems: true, + items: { + type: 'string', + enum: orderbyItems + } + } + }); + } + } +} + +/** + * Add parameter for query option $search + * @param {Array} parameters - Array of parameters to augment + * @param {string} target - Target container child of path + * @param {object} restrictions - Navigation property restrictions of navigation segment + * @param {string} queryOptionPrefix - Query option prefix + */ +function optionSearch(parameters, target, restrictions, queryOptionPrefix = '$') { + const searchRestrictions = restrictions.SearchRestrictions || (target && target['Org.OData.Capabilities.V1.SearchRestrictions']) || {}; + + if (searchRestrictions.Searchable !== false) { + if (searchRestrictions['Org.OData.Core.V1.Description']) { + parameters.push({ + name: queryOptionPrefix + 'search', + description: searchRestrictions['Org.OData.Core.V1.Description'], + in: 'query', + schema: { type: 'string' } + }); + } else { + parameters.push({ $ref: '#/components/parameters/search' }); + } + } +} + +/** + * Add parameter for query option $select + * @param {Array} parameters - Array of parameters to augment + * @param {object} element - Model element + * @param {Function} modelElement - Function to get model element + * @param {Function} propertiesOfStructuredType - Function to get properties + * @param {object} restrictions - Navigation property restrictions + * @param {object} nonExpandable - Non-expandable properties + * @param {string} queryOptionPrefix - Query option prefix + */ +function optionSelect(parameters, element, modelElement, propertiesOfStructuredType, restrictions, nonExpandable, queryOptionPrefix = '$') { + const selectSupport = restrictions.SelectSupport || {}; + + if (selectSupport.Supported !== false) { + const selectItems = []; + + // Add primitive properties + primitivePaths(element, modelElement, propertiesOfStructuredType).forEach(path => { + selectItems.push(path); + }); + + // Add navigation properties if allowed + if (selectSupport.Expandable !== false) { + const type = modelElement(element.$Type); + const properties = propertiesOfStructuredType(type); + Object.keys(properties).forEach(key => { + if (properties[key].$Kind === 'NavigationProperty' && !nonExpandable[key]) { + selectItems.push(key); + } + }); + } + + if (selectItems.length > 0) { + parameters.push({ + name: queryOptionPrefix + 'select', + description: 'Select properties to be returned, see [Select](http://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part1-protocol.html#sec_SystemQueryOptionselect)', + in: 'query', + explode: false, + schema: { + type: 'array', + uniqueItems: true, + items: { + type: 'string', + enum: selectItems + } + } + }); + } + } +} + +/** + * Add parameter for query option $expand + * @param {Array} parameters - Array of parameters to augment + * @param {object} element - Model element + * @param {Function} modelElement - Function to get model element + * @param {Function} navigationPaths - Function to get navigation paths + * @param {object} restrictions - Navigation property restrictions + * @param {object} nonExpandable - Non-expandable properties + * @param {number} level - Navigation level + * @param {number} maxLevels - Maximum levels + * @param {string} queryOptionPrefix - Query option prefix + */ +function optionExpand(parameters, element, modelElement, navigationPaths, restrictions, nonExpandable, level, maxLevels, queryOptionPrefix = '$') { + const expandRestrictions = restrictions.ExpandRestrictions || {}; + + if (expandRestrictions.Expandable !== false && level < maxLevels) { + const paths = navigationPaths(element, modelElement, maxLevels); + const expandItems = paths.filter(path => !nonExpandable[path]); + + if (expandItems.length > 0) { + parameters.push({ + name: queryOptionPrefix + 'expand', + description: 'Expand related entities, see [Expand](http://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part1-protocol.html#sec_SystemQueryOptionexpand)', + in: 'query', + explode: false, + schema: { + type: 'array', + uniqueItems: true, + items: { + type: 'string', + enum: expandItems + } + } + }); + } + } +} + +/** + * Build standard OData component parameters + * @param {object} options - Options including queryOptionPrefix + * @return {object} Component parameters object + */ +function buildComponentParameters(options = {}) { + const { queryOptionPrefix = '$' } = options; + + return { + top: { + name: queryOptionPrefix + 'top', + description: 'Show only the first n items, see [Paging - Top](http://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part1-protocol.html#sec_SystemQueryOptiontop)', + in: 'query', + schema: { + type: 'integer', + minimum: 0 + }, + example: 50 + }, + skip: { + name: queryOptionPrefix + 'skip', + description: 'Skip the first n items, see [Paging - Skip](http://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part1-protocol.html#sec_SystemQueryOptionskip)', + in: 'query', + schema: { + type: 'integer', + minimum: 0 + } + }, + count: { + name: queryOptionPrefix + 'count', + description: 'Include count of items, see [Count](http://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part1-protocol.html#sec_SystemQueryOptioncount)', + in: 'query', + schema: { + type: 'boolean' + } + }, + search: { + name: queryOptionPrefix + 'search', + description: 'Search items by search phrases, see [Searching](http://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part1-protocol.html#sec_SystemQueryOptionsearch)', + in: 'query', + schema: { + type: 'string' + } + } + }; +} + +module.exports = { + addQueryOptions, + optionTop, + optionSkip, + optionCount, + optionFilter, + optionOrderBy, + optionSearch, + optionSelect, + optionExpand, + buildComponentParameters +}; \ No newline at end of file diff --git a/lib/compile/modules/builders/paths.js b/lib/compile/modules/builders/paths.js new file mode 100644 index 0000000..f575096 --- /dev/null +++ b/lib/compile/modules/builders/paths.js @@ -0,0 +1,299 @@ +/** + * Path Building Module + * + * This module contains all functions related to building OpenAPI paths + * from CDS model elements. + */ + +const { nameParts, isIdentifier } = require('../utils/naming'); +const { assert } = require('../utils/errors'); +const { Logger } = require('../utils/logger'); + +const logger = new Logger('csdl2openapi:paths'); +const DEBUG = logger.debug.bind(logger); + +/** + * Extract path value prefix based on type + * @param {string} typename - The type name + * @param {boolean} keyAsSegment - Whether key is used as segment + * @return {string} value prefix + */ +function pathValuePrefix(typename, keyAsSegment) { + //TODO: handle other Edm types, enumeration types, and type definitions + if (['Edm.Int64', 'Edm.Int32', 'Edm.Int16', 'Edm.SByte', 'Edm.Byte', + 'Edm.Double', 'Edm.Single', 'Edm.Date', 'Edm.DateTimeOffset', 'Edm.Guid'].includes(typename)) return ''; + if (keyAsSegment) return ''; + return `'`; +} + +/** + * Extract path value suffix based on type + * @param {string} typename - The type name + * @param {boolean} keyAsSegment - Whether key is used as segment + * @return {string} value suffix + */ +function pathValueSuffix(typename, keyAsSegment) { + //TODO: handle other Edm types, enumeration types, and type definitions + if (['Edm.Int64', 'Edm.Int32', 'Edm.Int16', 'Edm.SByte', 'Edm.Byte', + 'Edm.Double', 'Edm.Single', 'Edm.Date', 'Edm.DateTimeOffset', 'Edm.Guid'].includes(typename)) return ''; + if (keyAsSegment) return ''; + return `'`; +} + +/** + * Unpack NavigationPropertyPath value if it uses CSDL JSON CS01 style + * @param {string|object} path - Qualified name of referenced type + * @return {string} Navigation property path + */ +function navigationPropertyPath(path) { + if (typeof path == 'string') + return path; + else + return path.$NavigationPropertyPath; +} + +/** + * Unpack PropertyPath value if it uses CSDL JSON CS01 style + * @param {string|object} path - Qualified name of referenced type + * @return {string} Property path + */ +function propertyPath(path) { + if (typeof path == 'string') + return path; + else + return path.$PropertyPath; +} + +/** + * Build navigation paths from element + * @param {object} element - Model element + * @param {Function} modelElement - Function to get model element + * @param {Function} propertiesOfStructuredType - Function to get properties + * @param {string} prefix - Path prefix + * @param {number} level - Navigation level + * @param {number} maxLevels - Maximum navigation levels + * @return {Array} Array of navigation property paths + */ +function navigationPaths(element, modelElement, propertiesOfStructuredType, prefix = '', level = 0, maxLevels) { + const paths = []; + const type = modelElement(element.$Type); + const properties = propertiesOfStructuredType(type); + Object.keys(properties).forEach(key => { + if (properties[key].$Kind == 'NavigationProperty') { + paths.push(prefix + key); + if (!properties[key].$ContainsTarget && level < maxLevels) { + const target = modelElement(properties[key].$Type); + if (target && target.$Kind == 'EntityType') { + const targetPaths = navigationPaths(target, modelElement, propertiesOfStructuredType, + prefix + key + '/', level + 1, maxLevels); + paths.push(...targetPaths); + } + } + } else if (properties[key].$Type && !properties[key].$Collection && level < maxLevels) { + const complexType = modelElement(properties[key].$Type); + if (complexType && complexType.$Kind == 'ComplexType') { + const complexPaths = navigationPaths({ $Type: properties[key].$Type }, + modelElement, propertiesOfStructuredType, prefix + key + '/', level + 1, maxLevels); + paths.push(...complexPaths); + } + } + }); + return paths; +} + +/** + * Create a map of navigation property paths and their types + * @param {object} type - Type to analyze + * @param {Function} propertiesOfStructuredType - Function to get properties + * @param {Function} modelElement - Function to get model element + * @param {object} map - Map to populate + * @param {string} prefix - Path prefix + * @param {number} level - Current level + * @param {number} maxLevels - Maximum levels + * @return {object} Map of navigation property paths and their types + */ +function navigationPathMap(type, propertiesOfStructuredType, modelElement, map = {}, prefix = '', level = 0, maxLevels) { + const properties = propertiesOfStructuredType(type); + Object.keys(properties).forEach(key => { + if (properties[key].$Kind == 'NavigationProperty') { + map[prefix + key] = properties[key]; + } else if (properties[key].$Type && !properties[key].$Collection && level < maxLevels) { + const complexType = modelElement(properties[key].$Type); + if (complexType && complexType.$Kind == 'ComplexType') { + navigationPathMap(complexType, propertiesOfStructuredType, modelElement, + map, prefix + key + '/', level + 1, maxLevels); + } + } + }); + return map; +} + +/** + * Collect primitive paths of a navigation segment and its potentially structured components + * @param {object} element - Model element of navigation segment + * @param {Function} modelElement - Function to get model element + * @param {Function} propertiesOfStructuredType - Function to get properties + * @param {string} prefix - Navigation prefix + * @return {Array} Array of primitive property paths + */ +function primitivePaths(element, modelElement, propertiesOfStructuredType, prefix = '') { + const paths = []; + const elementType = modelElement(element.$Type); + + if (!elementType) { + DEBUG?.(`Unknown type for element: ${JSON.stringify(element)}`); + return paths; + } + + const propsOfType = propertiesOfStructuredType(elementType); + const ignore = Object.entries(propsOfType) + .filter(entry => entry[1].$Kind !== 'NavigationProperty') + .filter(entry => entry[1].$Type) + .filter(entry => nameParts(entry[1].$Type).qualifier !== 'Edm') + .filter(entry => !modelElement(entry[1].$Type)); + + // Keep old logging + ignore.forEach(entry => DEBUG?.(`Unknown type for element: ${JSON.stringify(entry)}`)); + + const properties = Object.entries(propsOfType) + .filter(entry => entry[1].$Kind !== 'NavigationProperty') + .filter(entry => !ignore.includes(entry)) + .map(entryToProperty({ path: prefix, typeRefChain: [] }, modelElement, propertiesOfStructuredType)); + + for (let i = 0; i < properties.length; i++) { + const property = properties[i]; + if (!property.isComplex) { + paths.push(property.path); + continue; + } + + const typeRefChainTail = property.typeRefChain[property.typeRefChain.length - 1]; + + // Allow full cycle to be shown (0) times + if (property.typeRefChain.filter(_type => _type === typeRefChainTail).length > 1) { + DEBUG?.(`Cycle detected ${property.typeRefChain.join('->')}`); + continue; + } + + const expanded = Object.entries(property.properties) + .filter(pProperty => pProperty[1].$Kind !== 'NavigationProperty') + .map(entryToProperty(property, modelElement, propertiesOfStructuredType)); + properties.splice(i + 1, 0, ...expanded); + } + + return paths; +} + +/** + * Helper function to convert entry to property + * @param {object} parent - Parent property + * @param {Function} modelElement - Function to get model element + * @param {Function} propertiesOfStructuredType - Function to get properties + * @return {Function} Function that converts entry to property + */ +function entryToProperty(parent, modelElement, propertiesOfStructuredType) { + return function (entry) { + const key = entry[0]; + const property = entry[1]; + const propertyType = property.$Type && modelElement(property.$Type); + + if (propertyType && propertyType.$Kind && propertyType.$Kind === 'ComplexType') { + return { + properties: propertiesOfStructuredType(propertyType), + path: `${parent.path}${key}/`, + typeRefChain: parent.typeRefChain.concat(property.$Type), + isComplex: true + } + } + + return { + properties: {}, + path: `${parent.path}${key}`, + typeRefChain: [], + isComplex: false, + } + }; +} + +/** + * Build path parameters for key properties + * @param {object} keyNames - Key property names + * @param {object} properties - Properties of the type + * @param {string} level - Navigation level + * @param {object} options - Options object with keyAsSegment flag + * @return {Array} Array of parameter objects + */ +function buildKeyParameters(keyNames, properties, level, options = {}) { + const { keyAsSegment } = options; + const parameters = []; + + keyNames.forEach(name => { + const property = properties[name]; + const param = { + name: name + '-' + level, + in: 'path', + required: true, + description: property[property.$Type === 'Edm.String' ? 'Core.Description' : '$Type'] + || `key: ${name}`, + schema: { + type: property.$Type === 'Edm.String' ? 'string' : + ['Edm.Int64', 'Edm.Int32', 'Edm.Int16', 'Edm.SByte', 'Edm.Byte'].includes(property.$Type) ? 'integer' : + 'string' + } + }; + + // Add format for specific types + if (property.$Type === 'Edm.Int64') param.schema.format = 'int64'; + if (property.$Type === 'Edm.Int32') param.schema.format = 'int32'; + if (property.$Type === 'Edm.Guid') param.schema.pattern = '^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$'; + + parameters.push(param); + }); + + return parameters; +} + +/** + * Build path template with key parameters + * @param {string} prefix - Path prefix + * @param {Array} keyNames - Key property names + * @param {object} properties - Properties of the type + * @param {number} level - Navigation level + * @param {object} options - Options including keyAsSegment flag + * @return {string} Path template + */ +function buildPathWithKeys(prefix, keyNames, properties, level, options = {}) { + const { keyAsSegment } = options; + + if (keyAsSegment) { + // Key as segment style: /path/keyValue + return keyNames.map(name => { + const property = properties[name]; + const valuePrefix = pathValuePrefix(property.$Type, keyAsSegment); + const valueSuffix = pathValueSuffix(property.$Type, keyAsSegment); + return `${prefix}/${valuePrefix}{${name}-${level}}${valueSuffix}`; + }).join(''); + } else { + // Parentheses style: /path(key=value) + const keyParams = keyNames.map(name => { + const property = properties[name]; + const valuePrefix = pathValuePrefix(property.$Type, keyAsSegment); + const valueSuffix = pathValueSuffix(property.$Type, keyAsSegment); + return `${name}=${valuePrefix}{${name}-${level}}${valueSuffix}`; + }).join(','); + return `${prefix}(${keyParams})`; + } +} + +module.exports = { + pathValuePrefix, + pathValueSuffix, + navigationPropertyPath, + propertyPath, + navigationPaths, + navigationPathMap, + primitivePaths, + entryToProperty, + buildKeyParameters, + buildPathWithKeys +}; \ No newline at end of file diff --git a/lib/compile/modules/builders/responses.js b/lib/compile/modules/builders/responses.js new file mode 100644 index 0000000..c157314 --- /dev/null +++ b/lib/compile/modules/builders/responses.js @@ -0,0 +1,287 @@ +/** + * Response Building Module + * + * This module contains all functions related to building OpenAPI responses + * from CDS model elements. + */ + +const { Logger } = require('../utils/logger'); + +const logger = new Logger('csdl2openapi:responses'); +const DEBUG = logger.debug.bind(logger); + +/** + * Build response object for collection + * @param {object} element - Model element + * @param {string} description - Response description + * @param {object} options - Options including csdlVersion + * @return {object} Response object + */ +function collectionResponse(element, description, options = {}) { + const { csdlVersion = '4.0' } = options; + + return { + description: description || 'Retrieved entities', + content: { + 'application/json': { + schema: { + type: 'object', + title: 'Collection of ' + element.$Type, + properties: { + '@odata.count': { + $ref: '#/components/schemas/count' + }, + value: { + type: 'array', + items: { + $ref: '#/components/schemas/' + element.$Type.replace(/\./g, '_') + } + } + } + } + } + } + }; +} + +/** + * Build response object for single entity + * @param {object} element - Model element + * @param {string} description - Response description + * @return {object} Response object + */ +function entityResponse(element, description) { + return { + description: description || 'Retrieved entity', + content: { + 'application/json': { + schema: { + $ref: '#/components/schemas/' + element.$Type.replace(/\./g, '_') + } + } + } + }; +} + +/** + * Build response object for action/function result + * @param {object} returnType - Return type definition + * @param {string} description - Response description + * @param {Function} modelElement - Function to get model element + * @return {object} Response object + */ +function operationResponse(returnType, description, modelElement) { + if (!returnType || !returnType.$Type) { + return { + description: description || 'Success', + content: {} + }; + } + + const response = { + description: description || 'Success', + content: { + 'application/json': { + schema: {} + } + } + }; + + const schema = response.content['application/json'].schema; + + if (returnType.$Collection) { + schema.type = 'object'; + schema.title = `Collection of ${returnType.$Type}`; + schema.properties = { + '@odata.count': { + $ref: '#/components/schemas/count' + }, + value: { + type: 'array', + items: getTypeSchema(returnType.$Type, modelElement) + } + }; + } else { + Object.assign(schema, getTypeSchema(returnType.$Type, modelElement)); + } + + return response; +} + +/** + * Get schema for a type + * @param {string} typeName - Type name + * @param {Function} modelElement - Function to get model element + * @return {object} Schema object + */ +function getTypeSchema(typeName, modelElement) { + // Check if it's an Edm type + if (typeName.startsWith('Edm.')) { + return getEdmTypeSchema(typeName); + } + + // Check if it's a model type + const type = modelElement(typeName); + if (type) { + return { $ref: '#/components/schemas/' + typeName.replace(/\./g, '_') }; + } + + // Default to string + DEBUG?.(`Unknown type: ${typeName}, defaulting to string`); + return { type: 'string' }; +} + +/** + * Get OpenAPI schema for EDM type + * @param {string} typeName - EDM type name + * @return {object} Schema object + */ +function getEdmTypeSchema(typeName) { + const edmTypeMap = { + 'Edm.Binary': { type: 'string', format: 'base64' }, + 'Edm.Boolean': { type: 'boolean' }, + 'Edm.Byte': { type: 'integer', format: 'uint8' }, + 'Edm.Date': { type: 'string', format: 'date' }, + 'Edm.DateTimeOffset': { type: 'string', format: 'date-time' }, + 'Edm.Decimal': { type: 'number', format: 'decimal' }, + 'Edm.Double': { type: 'number', format: 'double' }, + 'Edm.Duration': { type: 'string', format: 'duration' }, + 'Edm.Guid': { + type: 'string', + format: 'uuid', + pattern: '^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$' + }, + 'Edm.Int16': { type: 'integer', format: 'int16' }, + 'Edm.Int32': { type: 'integer', format: 'int32' }, + 'Edm.Int64': { type: 'integer', format: 'int64' }, + 'Edm.SByte': { type: 'integer', format: 'int8' }, + 'Edm.Single': { type: 'number', format: 'float' }, + 'Edm.String': { type: 'string' }, + 'Edm.TimeOfDay': { type: 'string', format: 'time' }, + 'Edm.Geography': { type: 'object' }, + 'Edm.GeographyPoint': { type: 'object' }, + 'Edm.GeographyLineString': { type: 'object' }, + 'Edm.GeographyPolygon': { type: 'object' }, + 'Edm.GeographyMultiPoint': { type: 'object' }, + 'Edm.GeographyMultiLineString': { type: 'object' }, + 'Edm.GeographyMultiPolygon': { type: 'object' }, + 'Edm.GeographyCollection': { type: 'object' }, + 'Edm.Geometry': { type: 'object' }, + 'Edm.GeometryPoint': { type: 'object' }, + 'Edm.GeometryLineString': { type: 'object' }, + 'Edm.GeometryPolygon': { type: 'object' }, + 'Edm.GeometryMultiPoint': { type: 'object' }, + 'Edm.GeometryMultiLineString': { type: 'object' }, + 'Edm.GeometryMultiPolygon': { type: 'object' }, + 'Edm.GeometryCollection': { type: 'object' }, + 'Edm.Stream': { type: 'string', format: 'binary' } + }; + + return edmTypeMap[typeName] || { type: 'string' }; +} + +/** + * Build error response object + * @param {string} description - Error description + * @return {object} Error response object + */ +function errorResponse(description) { + return { + description: description || 'Error', + content: { + 'application/json': { + schema: { + $ref: '#/components/schemas/error' + } + } + } + }; +} + +/** + * Build standard OData responses + * @return {object} Standard responses object + */ +function buildStandardResponses() { + return { + error: errorResponse('Error'), + '400': errorResponse('Bad Request'), + '401': errorResponse('Unauthorized'), + '403': errorResponse('Forbidden'), + '404': errorResponse('Not Found'), + '500': errorResponse('Internal Server Error'), + '501': errorResponse('Not Implemented') + }; +} + +/** + * Build response for $count endpoint + * @return {object} Count response object + */ +function countResponse() { + return { + description: 'The count of the resource', + content: { + 'text/plain': { + schema: { + type: 'integer', + minimum: 0 + } + } + } + }; +} + +/** + * Build response for batch endpoint + * @return {object} Batch response object + */ +function batchResponse() { + return { + description: 'Batch response', + content: { + 'multipart/mixed': { + schema: { + type: 'string' + } + } + } + }; +} + +/** + * Build response with ETag support + * @param {object} baseResponse - Base response object + * @param {boolean} required - Whether ETag is required + * @return {object} Response with ETag headers + */ +function withETag(baseResponse, required = false) { + const response = JSON.parse(JSON.stringify(baseResponse)); // Deep clone + + response.headers = response.headers || {}; + response.headers.ETag = { + description: 'Entity tag', + schema: { + type: 'string' + } + }; + + if (required) { + response.headers.ETag.required = true; + } + + return response; +} + +module.exports = { + collectionResponse, + entityResponse, + operationResponse, + errorResponse, + countResponse, + batchResponse, + buildStandardResponses, + getTypeSchema, + getEdmTypeSchema, + withETag +}; \ No newline at end of file diff --git a/lib/compile/modules/utils/naming.js b/lib/compile/modules/utils/naming.js index 3e7f0d3..426d43a 100644 --- a/lib/compile/modules/utils/naming.js +++ b/lib/compile/modules/utils/naming.js @@ -45,9 +45,22 @@ function namespaceQualifiedName(qualifiedName, namespace) { return namespace[np.qualifier] + '.' + np.name; } +/** + * Unpack EnumMember value if it uses CSDL JSON CS01 style + * @param {string|object} member Enum member value + * @return {string} Unpacked enum member + */ +function enumMember(member) { + if (typeof member == 'string') + return member; + else if (typeof member == 'object') + return member.$EnumMember; +} + module.exports = { nameParts, isIdentifier, splitName, - namespaceQualifiedName + namespaceQualifiedName, + enumMember }; \ No newline at end of file From 0781b28c99325279fc9d20f5a44a222651c669d6 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Fri, 29 Aug 2025 16:41:40 +0000 Subject: [PATCH 2/3] Refactor csdl2openapi with modularized functions and improved code structure Co-authored-by: web.88002 --- IMPROVEMENTS.md | 24 +- lib/compile/csdl2openapi.backup.js | 2660 ---------------------------- lib/compile/csdl2openapi.js | 1485 +++++++++++++++- package.json | 1 + 4 files changed, 1467 insertions(+), 2703 deletions(-) delete mode 100644 lib/compile/csdl2openapi.backup.js diff --git a/IMPROVEMENTS.md b/IMPROVEMENTS.md index bacad90..283e400 100644 --- a/IMPROVEMENTS.md +++ b/IMPROVEMENTS.md @@ -24,19 +24,29 @@ This document outlines the improvements made to the @cap-js/openapi repository t - Added Jest configuration for TypeScript - Implemented build scripts with watch mode -### 3. Modularization (In Progress) 🚧 +### 3. Modularization ✅ - Created module structure: ``` lib/compile/modules/ - ├── constants/ # Extracted constants and configuration + ├── constants/ # Extracted constants and configuration ✅ ├── utils/ # Utility functions - │ ├── naming.js # Name processing utilities - │ ├── errors.js # Error handling utilities - │ └── logger.js # Logging utilities - ├── validators/ # Validation functions - ├── converters/ # Type conversion functions + │ ├── naming.js # Name processing utilities ✅ + │ ├── errors.js # Error handling utilities ✅ + │ └── logger.js # Logging utilities ✅ + ├── validators/ # Validation functions ✅ + ├── converters/ # Type conversion functions (planned) └── builders/ # OpenAPI builders + ├── paths.js # Path building functions ✅ + ├── parameters.js # Parameter building functions ✅ + ├── responses.js # Response building functions ✅ + └── schemas.js # Schema building functions (in progress) ``` +- Successfully extracted and modularized: + - Path building functions (navigationPaths, pathValuePrefix/Suffix, etc.) + - Parameter building functions (query options, component parameters) + - Response building functions (collection/entity/operation responses) +- Removed duplicate function definitions from main file +- All tests passing after refactoring ### 4. Error Handling Improvements ✅ - Created custom error classes: diff --git a/lib/compile/csdl2openapi.backup.js b/lib/compile/csdl2openapi.backup.js deleted file mode 100644 index cb9e605..0000000 --- a/lib/compile/csdl2openapi.backup.js +++ /dev/null @@ -1,2660 +0,0 @@ -/** - * Converts OData CSDL JSON to OpenAPI 3.0.2 -*/ -const cds = require('@sap/cds'); -var pluralize = require('pluralize') -const DEBUG = cds.debug('openapi'); // Initialize cds.debug with the 'openapi' - -// Import modularized components -const constants = require('./modules/constants'); -const { nameParts, isIdentifier, splitName, namespaceQualifiedName, enumMember } = require('./modules/utils/naming'); -const validators = require('./modules/validators'); -const { - pathValuePrefix, - pathValueSuffix, - navigationPropertyPath, - propertyPath, - navigationPaths, - navigationPathMap, - primitivePaths, - buildKeyParameters, - buildPathWithKeys -} = require('./modules/builders/paths'); -const { - addQueryOptions, - optionTop, - optionSkip, - optionCount, - optionFilter, - optionOrderBy, - optionSearch, - optionSelect, - optionExpand, - buildComponentParameters -} = require('./modules/builders/parameters'); -const { - collectionResponse, - entityResponse, - operationResponse, - errorResponse, - countResponse, - batchResponse, - buildStandardResponses, - getTypeSchema, - getEdmTypeSchema, - withETag -} = require('./modules/builders/responses'); - - -//TODO -// - Core.Example for complex types -// - reduce number of loops over schemas -// - inject $$name into each model element to make parameter passing easier? -// - allow passing additional files for referenced documents -// - delta: headers Prefer and Preference-Applied -// - inline definitions for Edm.* to make OpenAPI documents self-contained -// - both "clickable" and freestyle $expand, $select, $orderby - does not work yet, open issue for OpenAPI UI -// - system query options for actions/functions/imports depending on $Collection -// - 200 response for PATCH -// - ETag for GET / If-Match for PATCH and DELETE depending on @Core.OptimisticConcurrency -// - CountRestrictions for GET collection-valued (containment) navigation - https://issues.oasis-open.org/browse/ODATA-1300 -// - InsertRestrictions/NonInsertableProperties -// - InsertRestrictions/NonInsertableNavigationProperties -// - see //TODO comments below - -// Import constants from the constants module -const { SUFFIX, TITLE_SUFFIX, SYSTEM_QUERY_OPTIONS, ODM_ANNOTATIONS, ER_ANNOTATION_PREFIX, ER_ANNOTATIONS } = constants; - -/** - * Construct an OpenAPI description from a CSDL document - * @param {object} csdl CSDL document - * @param {object} options Optional parameters - * @return {object} OpenAPI description - */ -module.exports.csdl2openapi = function ( - csdl, - { - url: serviceRoot, - servers: serversObject, - odataVersion: odataVersion, - scheme: scheme = 'https', - host: host = 'localhost', - basePath: basePath = '/service-root', - diagram: diagram = false, - maxLevels: maxLevels = 5 - } = {} -) { - // as preProcess below mutates the csdl, copy it before, to avoid side-effects on the caller side - csdl = JSON.parse(JSON.stringify(csdl)) - csdl.$Version = odataVersion ? odataVersion : '4.01' - serviceRoot = serviceRoot || (scheme + '://' + host + basePath); - const queryOptionPrefix = csdl.$Version <= '4.01' ? '$' : ''; - const typesToInline = {}; // filled in schema() and used in inlineTypes() - const boundOverloads = {}; - const derivedTypes = {}; - const alias = {}; - const namespace = { 'Edm': 'Edm' }; - const namespaceUrl = {}; - const voc = {}; - const requiredSchemas = { list: [], used: {} }; - - preProcess(csdl, boundOverloads, derivedTypes, alias, namespace, namespaceUrl, voc); - - const entityContainer = csdl.$EntityContainer ? modelElement(csdl.$EntityContainer) : {}; - if (csdl.$EntityContainer) { - let serviceName = nameParts(csdl.$EntityContainer).qualifier; - Object.keys(entityContainer).forEach(element => { - if (entityContainer[element].$Type) { - let type = nameParts(entityContainer[element].$Type).name; - if ((csdl[serviceName]?.[type]?.['@cds.autoexpose'] || csdl[serviceName]?.[type]?.['@cds.autoexposed']) && !entityContainer[type]) - entityContainer[element]['$cds.autoexpose'] = true; - } - }); - } - - const keyAsSegment = entityContainer ? entityContainer[voc.Capabilities.KeyAsSegmentSupported] : {}; - - const openapi = { - openapi: '3.0.2', - info: getInfo(csdl, entityContainer), - 'x-sap-api-type': 'ODATAV4', - 'x-odata-version': csdl.$Version, - 'x-sap-shortText': getShortText(csdl, entityContainer), - servers: getServers(serviceRoot, serversObject), - tags: entityContainer ? getTags(entityContainer) : {}, - paths: entityContainer ? getPaths(entityContainer) : {}, - components: getComponents(csdl, entityContainer) - }; - - const externalDocs = getExternalDoc(csdl); - if (externalDocs && Object.keys(externalDocs).length > 0) { - openapi.externalDocs = externalDocs; - } - const extensions = getExtensions(csdl, 'root'); - if (extensions && Object.keys(extensions).length > 0) { - Object.assign(openapi, extensions); - } - - // function to read @OpenAPI.Extensions and get them in the generated openAPI document - function getExtensions(csdl, level) { - let extensionObj = {}; - let containerSchema = {}; - if (level ==='root'){ - const namespace = csdl.$EntityContainer ? nameParts(csdl.$EntityContainer).qualifier : null; - containerSchema = csdl.$EntityContainer ? csdl[namespace] : {}; - } - else if(level === 'schema' || level === 'operation'){ - containerSchema = csdl; - } - - for (const [key, value] of Object.entries(containerSchema)) { - if (key.startsWith('@OpenAPI.Extensions')) { - const annotationProperties = key.split('@OpenAPI.Extensions.')[1]; - const keys = annotationProperties.split('.'); - if (!keys[0].startsWith("x-sap-")) { - keys[0] = (keys[0].startsWith("sap-") ? "x-" : "x-sap-") + keys[0]; - } - if (keys.length === 1) { - extensionObj[keys[0]] = value; - } else { - nestedAnnotation(extensionObj, keys[0], keys, value); - } - } - } - let extensionEnums = { - "x-sap-compliance-level": {allowedValues: ["sap:base:v1", "sap:core:v1", "sap:core:v2" ] } , - "x-sap-api-type": {allowedValues: [ "ODATA", "ODATAV4", "REST" , "SOAP"] }, - "x-sap-direction": {allowedValues: ["inbound", "outbound", "mixed"] , default : "inbound" }, - "x-sap-dpp-entity-semantics": {allowedValues: ["sap:DataSubject", "sap:DataSubjectDetails", "sap:Other"] }, - "x-sap-dpp-field-semantics": {allowedValues: ["sap:DataSubjectID", "sap:ConsentID", "sap:PurposeID", "sap:ContractRelatedID", "sap:LegalEntityID", "sap:DataControllerID", "sap:UserID", "sap:EndOfBusinessDate", "sap:BlockingDate", "sap:EndOfRetentionDate"] }, - }; - checkForExtentionEnums(extensionObj, extensionEnums); - - let extenstionSchema = { - "x-sap-stateInfo": ['state', 'deprecationDate', 'decomissionedDate', 'link'], - "x-sap-ext-overview": ['name', 'values'], - "x-sap-deprecated-operation" : ['deprecationDate', 'successorOperationRef', "successorOperationId"], - "x-sap-odm-semantic-key" : ['name', 'values'], - }; - - checkForExtentionSchema(extensionObj, extenstionSchema); - return extensionObj; - } - - function checkForExtentionEnums(extensionObj, extensionEnums){ - for (const [key, value] of Object.entries(extensionObj)) { - if(extensionEnums[key] && extensionEnums[key].allowedValues && !extensionEnums[key].allowedValues.includes(value)){ - if(extensionEnums[key].default){ - extensionObj[key] = extensionEnums[key].default; - } - else{ - delete extensionObj[key]; - } - } - } - } - - function checkForExtentionSchema(extensionObj, extenstionSchema) { - for (const [key, value] of Object.entries(extensionObj)) { - if (extenstionSchema[key]) { - if (Array.isArray(value)) { - extensionObj[key] = value.filter((v) => extenstionSchema[key].includes(v)); - } else if (typeof value === "object" && value !== null) { - for (const field in value) { - if (!extenstionSchema[key].includes(field)) { - delete extensionObj[key][field]; - } - } - } - } - } - } - - - function nestedAnnotation(resObj, openapiProperty, keys, value) { - if (resObj[openapiProperty] === undefined) { - resObj[openapiProperty] = {}; - } - - let node = resObj[openapiProperty]; - - // traverse the annotation property and define the objects if they're not defined - for (let nestedIndex = 1; nestedIndex < keys.length - 1; nestedIndex++) { - const nestedElement = keys[nestedIndex]; - if (node[nestedElement] === undefined) { - node[nestedElement] = {}; - } - node = node[nestedElement]; - } - - // set value annotation property - node[keys[keys.length - 1]] = value; - } - - if (!csdl.$EntityContainer) { - delete openapi.servers; - delete openapi.tags; - } - - security(openapi, entityContainer); - - return openapi; - - - /** - * Collect model info for easier lookup - * @param {object} csdl CSDL document - * @param {object} boundOverloads Map of action/function names to bound overloads - * @param {object} derivedTypes Map of type names to derived types - * @param {object} alias Map of namespace or alias to alias - * @param {object} namespace Map of namespace or alias to namespace - * @param {object} namespaceUrl Map of namespace to reference URL - * @param {object} voc Map of vocabularies and terms - */ - function preProcess(csdl, boundOverloads, derivedTypes, alias, namespace, namespaceUrl, voc) { - Object.keys(csdl.$Reference || {}).forEach(url => { - const reference = csdl.$Reference[url]; - (reference.$Include || []).forEach(include => { - const qualifier = include.$Alias || include.$Namespace; - alias[include.$Namespace] = qualifier; - namespace[qualifier] = include.$Namespace; - namespace[include.$Namespace] = include.$Namespace; - namespaceUrl[include.$Namespace] = url; - }); - }); - - getVocabularies(voc, alias); - - Object.keys(csdl).filter(name => isIdentifier(name)).forEach(name => { - const schema = csdl[name]; - const qualifier = schema.$Alias || name; - const isDefaultNamespace = schema[voc.Core.DefaultNamespace]; - - alias[name] = qualifier; - namespace[qualifier] = name; - namespace[name] = name; - - Object.keys(schema).filter(iName => isIdentifier(iName)).forEach(iName2 => { - const qualifiedName = qualifier + '.' + iName2; - const element = schema[iName2]; - if (Array.isArray(element)) { - element.filter(overload => overload.$IsBound).forEach(overload => { - const type = overload.$Parameter[0].$Type + (overload.$Parameter[0].$Collection ? '-c' : ''); - if (!boundOverloads[type]) boundOverloads[type] = []; - boundOverloads[type].push({ name: (isDefaultNamespace ? iName2 : qualifiedName), overload: overload }); - }); - } else if (element.$BaseType) { - const base = namespaceQualifiedName(element.$BaseType); - if (!derivedTypes[base]) derivedTypes[base] = []; - derivedTypes[base].push(qualifiedName); - } - }); - - Object.keys(schema.$Annotations || {}).forEach(target => { - const annotations = schema.$Annotations[target]; - const segments = target.split('/'); - const open = segments[0].indexOf('('); - let element; - if (open == -1) { - element = modelElement(segments[0]); - } else { - element = modelElement(segments[0].substring(0, open)); - let args = segments[0].substring(open + 1, segments[0].length - 1); - element = element.find( - (overload) => - (overload.$Kind == "Action" && - overload.$IsBound != true && - args == "") || - (overload.$Kind == "Action" && - args == - (overload.$Parameter[0].$Collection - ? `Collection(${overload.$Parameter[0].$Type})` - : overload.$Parameter[0].$Type || "")) || - (overload.$Parameter || []) - .map((p) => { - const type = p.$Type || "Edm.String"; - return p.$Collection ? `Collection(${type})` : type; - }) - .join(",") == args - ); - } - if (!element) { - DEBUG?.(`Invalid annotation target '${target}'`); - } else if (Array.isArray(element)) { - //TODO: action or function: - //- loop over all overloads - //- if there are more segments, a parameter or the return type is targeted - } else { - switch (segments.length) { - case 1: - Object.assign(element, annotations); - break; - case 2: - if (['Action', 'Function'].includes(element.$Kind)) { - if (segments[1] == '$ReturnType') { - if (element.$ReturnType) - Object.assign(element.$ReturnType, annotations); - } else { - const parameter = element.$Parameter.find(p => p.$Name == segments[1]); - Object.assign(parameter, annotations); - } - } else { - if (element[segments[1]]) { - Object.assign(element[segments[1]], annotations); - } else { - // DEBUG?.(`Invalid annotation target '${target}'`) - } - } - break; - default: - DEBUG?.('More than two annotation target path segments'); - } - } - }); - }); - } - - /** - * Construct map of qualified term names - * @param {object} voc Map of vocabularies and terms - * @param {object} alias Map of namespace or alias to alias - */ - function getVocabularies(voc, alias) { - const terms = { - Authorization: ['Authorizations', 'SecuritySchemes'], - Capabilities: ['BatchSupport', 'BatchSupported', 'ChangeTracking', 'CountRestrictions', 'DeleteRestrictions', 'DeepUpdateSupport', 'ExpandRestrictions', - 'FilterRestrictions', 'IndexableByKey', 'InsertRestrictions', 'KeyAsSegmentSupported', 'NavigationRestrictions', 'OperationRestrictions', - 'ReadRestrictions', 'SearchRestrictions', 'SelectSupport', 'SkipSupported', 'SortRestrictions', 'TopSupported', 'UpdateRestrictions'], - Core: ['AcceptableMediaTypes', 'Computed', 'ComputedDefaultValue', 'DefaultNamespace', 'Description', 'Example', 'Immutable', 'LongDescription', - 'OptionalParameter', 'Permissions', 'SchemaVersion'], - JSON: ['Schema'], - Validation: ['AllowedValues', 'Exclusive', 'Maximum', 'Minimum', 'Pattern'] - }; - - Object.keys(terms).forEach(vocab => { - voc[vocab] = {}; - terms[vocab].forEach(term => { - if (alias['Org.OData.' + vocab + '.V1'] != undefined) - voc[vocab][term] = '@' + alias['Org.OData.' + vocab + '.V1'] + '.' + term; - }); - }); - - voc.Common = { - Label: `@${alias['com.sap.vocabularies.Common.v1']}.Label` - } - } - - /** - * Construct the Info Object - * @param {object} csdl CSDL document - * @param {object} entityContainer Entity Container object - * @return {object} Info Object - */ - function getInfo(csdl, entityContainer) { - const namespace = csdl.$EntityContainer ? nameParts(csdl.$EntityContainer).qualifier : null; - const containerSchema = csdl.$EntityContainer ? csdl[namespace] : {}; - let description; - if (entityContainer && entityContainer[voc.Core.LongDescription]) { - description = entityContainer[voc.Core.LongDescription]; - } - else if (containerSchema && containerSchema[voc.Core.LongDescription]) { - description = containerSchema[voc.Core.LongDescription]; - } - else { - description = "Use @Core.LongDescription: '...' on your CDS service to provide a meaningful description."; - } - description += (diagram ? getResourceDiagram(csdl, entityContainer) : ''); - let title; - if (entityContainer && entityContainer[voc.Common.Label]) { - title = entityContainer[voc.Common.Label]; - } - else { - title = "Use @title: '...' on your CDS service to provide a meaningful title."; - } - return { - title: title, - description: csdl.$EntityContainer ? description : '', - version: containerSchema[voc.Core.SchemaVersion] || '' - }; - } - - /** - * Construct the externalDocs Object - * @param {object} csdl CSDL document - * @return {object} externalDocs Object - */ - function getExternalDoc(csdl) { - const namespace = csdl.$EntityContainer ? nameParts(csdl.$EntityContainer).qualifier : null; - const containerSchema = csdl.$EntityContainer ? csdl[namespace] : {}; - let externalDocs = {}; - if (containerSchema?.['@OpenAPI.externalDocs.description']) { - externalDocs.description = containerSchema['@OpenAPI.externalDocs.description']; - } - if (containerSchema?.['@OpenAPI.externalDocs.url']) { - externalDocs.url = containerSchema['@OpenAPI.externalDocs.url']; - } - return externalDocs; - } - - /** - * Construct resource diagram using web service at https://yuml.me - * @param {object} csdl CSDL document - * @param {object} entityContainer Entity Container object - * @return {string} resource diagram - */ - function getResourceDiagram(csdl, entityContainer) { - let diagram = ''; - let comma = ''; - //TODO: make colors configurable - let color = { resource: '{bg:lawngreen}', entityType: '{bg:lightslategray}', complexType: '', external: '{bg:whitesmoke}' } - - Object.keys(csdl).filter(name => isIdentifier(name)).forEach(namespace => { - const schema = csdl[namespace]; - Object.keys(schema).filter(name => isIdentifier(name) && ['EntityType', 'ComplexType'].includes(schema[name].$Kind)) - .forEach(typeName => { - const type = schema[typeName]; - diagram += comma - + (type.$BaseType ? '[' + nameParts(type.$BaseType).name + ']^' : '') - + '[' + typeName + (type.$Kind == 'EntityType' ? color.entityType : color.complexType) + ']'; - Object.keys(type).filter(name => isIdentifier(name)).forEach(propertyName => { - const property = type[propertyName]; - const targetNP = nameParts(property.$Type || 'Edm.String'); - if (property.$Kind == 'NavigationProperty' || targetNP.qualifier != 'Edm') { - const target = modelElement(property.$Type); - const bidirectional = property.$Partner && target && target[property.$Partner] && target[property.$Partner].$Partner == propertyName; - // Note: if the partner has the same name then it will also be depicted - if (!bidirectional || propertyName <= property.$Partner) { - diagram += ',[' + typeName + ']' - + ((property.$Kind != 'NavigationProperty' || property.$ContainsTarget) ? '++' : (bidirectional ? cardinality(target[property.$Partner]) : '')) - + '-' - + cardinality(property) - + ((property.$Kind != 'NavigationProperty' || bidirectional) ? '' : '>') - + '[' - + (target ? targetNP.name : property.$Type + color.external) - + ']'; - } - } - }); - comma = ','; - }); - }); - - Object.keys(entityContainer).filter(name => isIdentifier(name)).reverse().forEach(name => { - const resource = entityContainer[name]; - if (resource.$Type) { - diagram += comma - + '[' + name + '%20' + color.resource + ']' // additional space in case entity set and type have same name - + '++-' - + cardinality(resource) - + '>[' + nameParts(resource.$Type).name + ']'; - } else { - if (resource.$Action) { - diagram += comma - + '[' + name + color.resource + ']'; - const overload = modelElement(resource.$Action).find(pOverload => !pOverload.$IsBound); - diagram += overloadDiagram(name, overload); - } else if (resource.$Function) { - diagram += comma - + '[' + name + color.resource + ']'; - const overloads = modelElement(resource.$Function); - if (overloads) { - const unbound = overloads.filter(overload => !overload.$IsBound); - // TODO: loop over all overloads, add new source box after first arrow - diagram += overloadDiagram(name, unbound[0]); - } - } - } - }); - - if (diagram != '') { - diagram = '\n\n## Entity Data Model\n![ER Diagram](https://yuml.me/diagram/class/' - + diagram - + ')\n\n### Legend\n![Legend](https://yuml.me/diagram/plain;dir:TB;scale:60/class/[External.Type' + color.external - + '],[ComplexType' + color.complexType + '],[EntityType' + color.entityType - + '],[EntitySet/Singleton/Operation' + color.resource + '])'; - } - - return diagram; - - /** - * Diagram representation of property cardinality - * @param {object} typedElement Typed model element, e.g. property - * @return {string} cardinality - */ - function cardinality(typedElement) { - return typedElement.$Collection ? '*' : (typedElement.$Nullable ? '0..1' : ''); - } - - /** - * Diagram representation of action or function overload - * @param {string} name Name of action or function import - * @param {object} overload Action or function overload - * @return {string} diagram part - */ - function overloadDiagram(name, overload) { - let diag = ""; - if (overload.$ReturnType) { - const type = modelElement(overload.$ReturnType.$Type || "Edm.String"); - if (type) { - diag += "-" + cardinality(overload.$ReturnType) + ">[" + nameParts(overload.$ReturnType.$Type).name + "]"; - } - } - for (const param of overload.$Parameter || []) { - const type = modelElement(param.$Type || "Edm.String"); - if (type) { - diag += comma + "[" + name + color.resource + "]in-" + cardinality(param.$Type) + ">[" + nameParts(param.$Type).name + "]"; - } - } - return diag; - } - } - - /** - * Find model element by qualified name - * @param {string} qname Qualified name of model element - * @return {object} Model element - */ - function modelElement(qname) { - const q = nameParts(qname); - const schema = csdl[q.qualifier] || csdl[namespace[q.qualifier]]; - return schema ? schema[q.name] : null; - } - - /** - * Construct the short text - * @param {object} csdl CSDL document - * @param {object} entityContainer Entity Container object - * @return {string} short text - */ - function getShortText(csdl, entityContainer) { - const namespace = csdl.$EntityContainer ? nameParts(csdl.$EntityContainer).qualifier : null; - const containerSchema = csdl.$EntityContainer ? csdl[namespace] : {}; - let shortText; - if (entityContainer && entityContainer[voc.Core.Description]) { - shortText = entityContainer[voc.Core.Description]; - } - else if (containerSchema && containerSchema[voc.Core.Description]) { - shortText = containerSchema[voc.Core.Description]; - } - else { - shortText = "Use @Core.Description: '...' on your CDS service to provide a meaningful short text."; - } - return shortText; - } - - /** - * Construct an array of Server Objects - * @param {object} serviceRoot The service root - * @param {object} serversObject Input servers object - * @return {Array} The list of servers - */ - function getServers(serviceRoot, serversObject) { - let servers; - if (serversObject) { - try { - servers = JSON.parse(serversObject); - } catch (err) { - throw new Error(`The input server object is invalid.`); - } - - if (!servers.length) { - throw new Error(`The input server object should be an array.`); - } - } else { - servers = [{ url: serviceRoot }]; - } - return servers; - } - - /** - * Construct an array of Tag Objects from the entity container - * @param {object} container The entity container - * @return {Array} The list of tags - */ - function getTags(container) { - const tags = new Map(); - // all entity sets and singletons - Object.keys(container) - .filter(name => isIdentifier(name) && container[name].$Type) - .forEach(child => { - const type = modelElement(container[child].$Type) || {}; - const tag = { - name: type[voc.Common.Label] || child - }; - const description = container[child][voc.Core.Description] || type[voc.Core.Description]; - if (description) tag.description = description; - tags.set(tag.name, tag); - }); - return Array.from(tags.values()).sort((pre, next) => pre.name.localeCompare(next.name)); - } - - /** - * Construct the Paths Object from the entity container - * @param {object} container Entity container - * @return {object} Paths Object - */ - function getPaths(container) { - const paths = {}; - const resources = Object.keys(container).filter(name => isIdentifier(name)); - resources.forEach(name => { - let child = container[name]; - if (child.$Type) { - const type = modelElement(child.$Type); - const sourceName = (type && type[voc.Common.Label]) || name; - // entity sets and singletons are almost containment navigation properties - child.$ContainsTarget = true; - pathItems(paths, '/' + name, [], child, child, sourceName, sourceName, child, 0, ''); - } else if (child.$Action) { - pathItemActionImport(paths, name, child); - } else if (child.$Function) { - pathItemFunctionImport(paths, name, child); - } else { - DEBUG?.('Unrecognized entity container child: ' + name); - } - }) - if (resources.length > 0) pathItemBatch(paths, container); - return Object.keys(paths).sort().reduce((p, c) => (p[c] = paths[c], p), {}); - } - - /** - * Add path and Path Item Object for a navigation segment - * @param {object} paths Paths Object to augment - * @param {string} prefix Prefix for path - * @param {Array} prefixParameters Parameter Objects for prefix - * @param {object} element Model element of navigation segment - * @param {object} root Root model element - * @param {string} sourceName Name of path source - * @param {string} targetName Name of path target - * @param {string} target Target container child of path - * @param {integer} level Number of navigation segments so far - * @param {string} navigationPath Path for finding navigation restrictions - */ - function pathItems(paths, prefix, prefixParameters, element, root, sourceName, targetName, target, level, navigationPath) { - const name = prefix.substring(prefix.lastIndexOf('/') + 1); - const type = modelElement(element.$Type); - const pathItem = {}; - const restrictions = navigationPropertyRestrictions(root, navigationPath); - const nonExpandable = nonExpandableProperties(root, navigationPath); - - paths[prefix] = pathItem; - if (prefixParameters.length > 0) pathItem.parameters = prefixParameters; - - operationRead(pathItem, element, name, sourceName, targetName, target, level, restrictions, false, nonExpandable); - if (!root['$cds.autoexpose'] && element.$Collection && (element.$ContainsTarget || level < 2 && target)) { - operationCreate(pathItem, element, name, sourceName, targetName, target, level, restrictions); - } - pathItemsForBoundOperations(paths, prefix, prefixParameters, element, sourceName); - - if (element.$ContainsTarget) { - if (element.$Collection) { - if (level < maxLevels) - pathItemsWithKey(paths, prefix, prefixParameters, element, root, sourceName, targetName, target, level, navigationPath, restrictions, nonExpandable); - } else { - if (!root['$cds.autoexpose']) { - operationUpdate(pathItem, element, name, sourceName, target, level, restrictions); - if (element.$Nullable) { - operationDelete(pathItem, element, name, sourceName, target, level, restrictions); - } - } - pathItemsForBoundOperations(paths, prefix, prefixParameters, element, sourceName); - pathItemsWithNavigation(paths, prefix, prefixParameters, type, root, sourceName, level, navigationPath); - } - } - - if (Object.keys(pathItem).filter((i) => i !== "parameters").length === 0) - delete paths[prefix]; - } - - /** - * Find navigation restrictions for a navigation path - * @param {object} root Root model element - * @param {string} navigationPath Path for finding navigation restrictions - * @return Navigation property restrictions of navigation segment - */ - function navigationPropertyRestrictions(root, navigationPath) { - const navigationRestrictions = root[voc.Capabilities.NavigationRestrictions] || {}; - return (navigationRestrictions.RestrictedProperties || []).find(item => navigationPropertyPath(item.NavigationProperty) == navigationPath) - || {}; - } - - /** - * Find non-expandable properties for a navigation path - * @param {object} root Root model element - * @param {string} navigationPath Path for finding navigation restrictions - * @return Navigation property restrictions of navigation segment - */ - function nonExpandableProperties(root, navigationPath) { - const expandRestrictions = root[voc.Capabilities.ExpandRestrictions] || {}; - const prefix = navigationPath.length === 0 ? '' : navigationPath + '/' - const from = prefix.length - const nonExpandable = [] - for (const path of (expandRestrictions.NonExpandableProperties || [])) { - if (path.startsWith(prefix)) { - nonExpandable.push(path.substring(from)) - } - } - return nonExpandable; - } - - /** - * Add path and Path Item Object for a navigation segment with key - * @param {object} paths Paths Object to augment - * @param {string} prefix Prefix for path - * @param {Array} prefixParameters Parameter Objects for prefix - * @param {object} element Model element of navigation segment - * @param {object} root Root model element - * @param {string} sourceName Name of path source - * @param {string} targetName Name of path target - * @param {string} target Target container child of path - * @param {integer} level Number of navigation segments so far - * @param {string} navigationPath Path for finding navigation restrictions - * @param {object} restrictions Navigation property restrictions of navigation segment - * @param {array} nonExpandable Non-expandable navigation properties - */ - function pathItemsWithKey(paths, prefix, prefixParameters, element, root, sourceName, targetName, target, level, navigationPath, restrictions, nonExpandable) { - const targetIndexable = target == null || target[voc.Capabilities.IndexableByKey] != false; - if (restrictions.IndexableByKey == true || restrictions.IndexableByKey != false && targetIndexable) { - const name = prefix.substring(prefix.lastIndexOf('/') + 1); - const type = modelElement(element.$Type); - const key = entityKey(type, level); - if (key.parameters.length > 0) { - const path = prefix + key.segment; - const parameters = prefixParameters.concat(key.parameters); - const pathItem = { parameters: parameters }; - paths[path] = pathItem; - - operationRead(pathItem, element, name, sourceName, targetName, target, level, restrictions, true, nonExpandable); - if (!root['$cds.autoexpose']) { - operationUpdate(pathItem, element, name, sourceName, target, level, restrictions, true); - operationDelete(pathItem, element, name, sourceName, target, level, restrictions, true); - } - if (Object.keys(pathItem).filter((i) => i !== "parameters").length === 0) - delete paths[path]; - - pathItemsForBoundOperations(paths, path, parameters, element, sourceName, true); - pathItemsWithNavigation(paths, path, parameters, type, root, sourceName, level, navigationPath); - } - } - } - - /** - * Construct Operation Object for create - * @param {object} pathItem Path Item Object to augment - * @param {object} element Model element of navigation segment - * @param {string} name Name of navigation segment - * @param {string} sourceName Name of path source - * @param {string} targetName Name of path target - * @param {string} target Target container child of path - * @param {integer} level Number of navigation segments so far - * @param {object} restrictions Navigation property restrictions of navigation segment - */ - function operationCreate(pathItem, element, name, sourceName, targetName, target, level, restrictions) { - const insertRestrictions = restrictions.InsertRestrictions || target && target[voc.Capabilities.InsertRestrictions] || {}; - let countRestrictions = target && (target[voc.Capabilities.CountRestrictions]?.Countable === false); // count property will be added if CountRestrictions is false - if (insertRestrictions.Insertable !== false) { - const lname = pluralize.singular(splitName(name)); - const type = modelElement(element.$Type); - pathItem.post = { - summary: insertRestrictions.Description || operationSummary('Creates', name, sourceName, level, true, true), - tags: [sourceName], - requestBody: { - description: type && type[voc.Core.Description] || 'New ' + lname, - required: true, - content: { - 'application/json': { - schema: ref(element.$Type, SUFFIX.create), - } - } - }, - responses: response(201, 'Created ' + lname, { $Type: element.$Type }, insertRestrictions.ErrorResponses, !countRestrictions), - }; - if (insertRestrictions.LongDescription) pathItem.post.description = insertRestrictions.LongDescription; - if (targetName && sourceName != targetName) pathItem.post.tags.push(targetName); - customParameters(pathItem.post, insertRestrictions); - } - } - - /** - * Split camel-cased name into words - * @param {string} name Name to split - * @return {string} Split name - */ - function splitName(name) { - return name.split(/(?=[A-Z])/g).join(' ').toLowerCase().replace(/ i d/g, ' id'); - } - - /** - * Construct operation summary - * @param {string} operation Operation (verb) - * @param {string} name Name of navigation segment - * @param {string} sourceName Name of path source - * @param {integer} level Number of navigation segments so far - * @param {boolean} collection Access a collection - * @param {boolean} byKey Access by key - * @return {string} Operation Text - */ - function operationSummary(operation, name, sourceName, level, collection, byKey) { - let lname = splitName(name); - let sname = splitName(sourceName); - - return operation + ' ' - + (byKey ? 'a single ' : (collection ? 'a list of ' : '')) - + (byKey ? pluralize.singular(lname) : lname) - //TODO: suppress "a" for all singletons - + (level == 0 ? '' : (level == 1 && sname == 'me' ? ' of me' : ' of a ' + pluralize.singular(sname))) - + '.' - } - - /** - * Construct Operation Object for read - * @param {object} pathItem Path Item Object to augment - * @param {object} element Model element of navigation segment - * @param {string} name Name of navigation segment - * @param {string} sourceName Name of path source - * @param {string} targetName Name of path target - * @param {string} target Target container child of path - * @param {integer} level Number of navigation segments so far - * @param {object} restrictions Navigation property restrictions of navigation segment - * @param {boolean} byKey Read by key - * @param {array} nonExpandable Non-expandable navigation properties - */ - function operationRead(pathItem, element, name, sourceName, targetName, target, level, restrictions, byKey, nonExpandable) { - const targetRestrictions = target?.[voc.Capabilities.ReadRestrictions]; - const readRestrictions = restrictions.ReadRestrictions || targetRestrictions || {}; - const readByKeyRestrictions = readRestrictions.ReadByKeyRestrictions; - let readable = true; - let countRestrictions = target && (target[voc.Capabilities.CountRestrictions]?.Countable === false); - if (byKey && readByKeyRestrictions && readByKeyRestrictions.Readable !== undefined) - readable = readByKeyRestrictions.Readable; - else if (readRestrictions.Readable !== undefined) - readable = readRestrictions.Readable; - - if (readable) { - let descriptions = (level == 0 ? targetRestrictions : restrictions.ReadRestrictions) || {}; - if (byKey) descriptions = descriptions.ReadByKeyRestrictions || {}; - const lname = splitName(name); - const collection = !byKey && element.$Collection; - const operation = { - summary: descriptions.Description || operationSummary('Retrieves', name, sourceName, level, element.$Collection, byKey), - tags: [sourceName], - parameters: [], - responses: response(200, 'Retrieved ' + (byKey ? pluralize.singular(lname) : lname), { $Type: element.$Type, $Collection: collection }, - byKey ? readByKeyRestrictions?.ErrorResponses : readRestrictions?.ErrorResponses, !countRestrictions) - }; - const deltaSupported = element[voc.Capabilities.ChangeTracking] && element[voc.Capabilities.ChangeTracking].Supported; - if (!byKey && deltaSupported) { - operation.responses[200].content['application/json'].schema.properties['@odata.deltaLink'] = { - type: 'string', - example: basePath + '/' + name + '?$deltatoken=opaque server-generated token for fetching the delta' - } - } - if (descriptions.LongDescription) operation.description = descriptions.LongDescription; - if (target && sourceName != targetName) operation.tags.push(targetName); - customParameters(operation, byKey ? readByKeyRestrictions || readRestrictions : readRestrictions); - - if (collection) { - optionTop(operation.parameters, target, restrictions); - optionSkip(operation.parameters, target, restrictions); - if (csdl.$Version >= '4.0') optionSearch(operation.parameters, target, restrictions); - optionFilter(operation.parameters, target, restrictions); - optionCount(operation.parameters, target); - optionOrderBy(operation.parameters, element, target, restrictions); - } - - optionSelect(operation.parameters, element, target, restrictions); - optionExpand(operation.parameters, element, target, nonExpandable); - - pathItem.get = operation; - } - } - - /** - * Add custom headers and query options - * @param {object} operation Operation object to augment - * @param {object} restrictions Restrictions for operation - */ - function customParameters(operation, restrictions) { - if ( - !operation.parameters && - (restrictions.CustomHeaders || restrictions.CustomQueryOptions) - ) - operation.parameters = []; - for (const custom of restrictions.CustomHeaders || []) { - operation.parameters.push(customParameter(custom, "header")); - } - - for (const custom of restrictions.CustomQueryOptions || []) { - operation.parameters.push(customParameter(custom, "query")); - } - } - - /** - * Construct custom parameter - * @param {object} custom custom parameter in OData format - * @param {string} location "header" or "query" - */ - function customParameter(custom, location) { - return { - name: custom.Name, - in: location, - required: custom.Required || false, - ...(custom.Description && { description: custom.Description }), - schema: { - type: "string", - ...(custom.DocumentationURL && { - externalDocs: { url: custom.DocumentationURL }, - }), - //TODO: Examples - }, - }; - } - - /** - * Add parameter for query option $count - * @param {Array} parameters Array of parameters to augment - * @param {string} target Target container child of path - */ - function optionCount(parameters, target) { - const targetRestrictions = target && target[voc.Capabilities.CountRestrictions]; - const targetCountable = target == null - || targetRestrictions == null - || targetRestrictions.Countable !== false; - - if (targetCountable) { - parameters.push({ - - $ref: '#/components/parameters/count' - }); - } - } - - /** - * Add parameter for query option $expand - * @param {Array} parameters Array of parameters to augment - * @param {object} element Model element of navigation segment - * @param {string} target Target container child of path - * @param {array} nonExpandable Non-expandable navigation properties - */ - function optionExpand(parameters, element, target, nonExpandable) { - const targetRestrictions = target && target[voc.Capabilities.ExpandRestrictions]; - const supported = targetRestrictions == null || targetRestrictions.Expandable != false; - if (supported) { - const expandItems = ['*'].concat(navigationPaths(element).filter(path => !nonExpandable.includes(path))); - if (expandItems.length > 1) { - parameters.push({ - name: queryOptionPrefix + 'expand', - description: (targetRestrictions && targetRestrictions[voc.Core.Description]) - || 'The value of $expand query option is a comma-separated list of navigation property names, \ -stream property names, or $value indicating the stream content of a media-entity. \ -The corresponding related entities and stream values will be represented inline, \ -see [Expand](http://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part1-protocol.html#sec_SystemQueryOptionexpand)', - in: 'query', - explode: false, - schema: { - type: 'array', - uniqueItems: true, - items: { - type: 'string', - enum: expandItems - } - } - }); - } - } - } - - /** - * Collect navigation paths of a navigation segment and its potentially structured components - * @param {object} element Model element of navigation segment - * @param {string} prefix Navigation prefix - * @param {integer} level Number of navigation segments so far - * @return {Array} Array of navigation property paths - */ - function navigationPaths(element, prefix = '', level = 0) { - const paths = []; - const type = modelElement(element.$Type); - const properties = propertiesOfStructuredType(type); - Object.keys(properties).forEach(key => { - if (properties[key].$Kind == 'NavigationProperty') { - paths.push(prefix + key) - } else if (properties[key].$Type && level < maxLevels) { - paths.push(...navigationPaths(properties[key], prefix + key + '/', level + 1)); - } - }) - return paths; - } - - /** - * Add parameter for query option $filter - * @param {Array} parameters Array of parameters to augment - * @param {string} target Target container child of path - * @param {object} restrictions Navigation property restrictions of navigation segment - */ - function optionFilter(parameters, target, restrictions) { - const filterRestrictions = restrictions.FilterRestrictions || target && target[voc.Capabilities.FilterRestrictions] || {}; - - if (filterRestrictions.Filterable !== false) { - const filter = { - name: queryOptionPrefix + 'filter', - description: filterRestrictions[voc.Core.Description] - || 'Filter items by property values, see [Filtering](http://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part1-protocol.html#sec_SystemQueryOptionfilter)', - in: 'query', - schema: { - type: 'string' - } - }; - if (filterRestrictions.RequiresFilter) - filter.required = true; - if (filterRestrictions.RequiredProperties) { - filter.description += '\n\nRequired filter properties:'; - filterRestrictions.RequiredProperties.forEach( - item => filter.description += '\n- ' + propertyPath(item) - ); - } - parameters.push(filter); - } - } - - /** - * Add parameter for query option $orderby - * @param {Array} parameters Array of parameters to augment - * @param {object} element Model element of navigation segment - * @param {string} target Target container child of path - * @param {object} restrictions Navigation property restrictions of navigation segment - */ - function optionOrderBy(parameters, element, target, restrictions) { - const sortRestrictions = restrictions.SortRestrictions || target && target[voc.Capabilities.SortRestrictions] || {}; - - if (sortRestrictions.Sortable !== false) { - const nonSortable = {}; - (sortRestrictions.NonSortableProperties || []).forEach(name => { - nonSortable[propertyPath(name)] = true; - }); - const orderbyItems = []; - primitivePaths(element).filter(property => !nonSortable[property]).forEach(property => { - orderbyItems.push(property); - orderbyItems.push(property + ' desc'); - }); - if (orderbyItems.length > 0) { - parameters.push({ - name: queryOptionPrefix + 'orderby', - description: sortRestrictions[voc.Core.Description] - || 'Order items by property values, see [Sorting](http://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part1-protocol.html#sec_SystemQueryOptionorderby)', - in: 'query', - explode: false, - schema: { - type: 'array', - uniqueItems: true, - items: { - type: 'string', - enum: orderbyItems - } - } - }); - } - } - } - - /** - * Unpack EnumMember value if it uses CSDL JSON CS01 style, like CAP does - * @param {string or object} path Qualified name of referenced type - * @return {object} Reference Object - */ - function enumMember(member) { - if (typeof member == 'string') - return member; - else if (typeof member == 'object') - return member.$EnumMember; - } - - /** - * Unpack NavigationPropertyPath value if it uses CSDL JSON CS01 style, like CAP does - * @param {string or object} path Qualified name of referenced type - * @return {object} Reference Object - */ - function navigationPropertyPath(path) { - if (typeof path == 'string') - return path; - else - return path.$NavigationPropertyPath; - } - - /** - * Unpack PropertyPath value if it uses CSDL JSON CS01 style, like CAP does - * @param {string or object} path Qualified name of referenced type - * @return {object} Reference Object - */ - function propertyPath(path) { - if (typeof path == 'string') - return path; - else - return path.$PropertyPath; - } - - /** - * Collect primitive paths of a navigation segment and its potentially structured components - * @param {object} element Model element of navigation segment - * @param {string} prefix Navigation prefix - * @return {Array} Array of primitive property paths - */ - function primitivePaths(element, prefix = '') { - const paths = []; - const elementType = modelElement(element.$Type); - - if (!elementType) { - DEBUG?.(`Unknown type for element: ${JSON.stringify(element)}`); - return paths; - } - - const propsOfType = propertiesOfStructuredType(elementType); - const ignore = Object.entries(propsOfType) - .filter(entry => entry[1].$Kind !== 'NavigationProperty') - .filter(entry => entry[1].$Type) - .filter(entry => nameParts(entry[1].$Type).qualifier !== 'Edm') - .filter(entry => !modelElement(entry[1].$Type)); - - // Keep old logging - ignore.forEach(entry => DEBUG?.(`Unknown type for element: ${JSON.stringify(entry)}`)); - - const properties = Object.entries(propsOfType) - .filter(entry => entry[1].$Kind !== 'NavigationProperty') - .filter(entry => !ignore.includes(entry)) - .map(entryToProperty({ path: prefix, typeRefChain: [] })); - - for (let i = 0; i < properties.length; i++) { - const property = properties[i]; - if (!property.isComplex) { - paths.push(property.path); - continue; - } - - const typeRefChainTail = property.typeRefChain[property.typeRefChain.length - 1]; - - // Allow full cycle to be shown (0) times - if (property.typeRefChain.filter(_type => _type === typeRefChainTail).length > 1) { - DEBUG?.(`Cycle detected ${property.typeRefChain.join('->')}`); - continue; - } - - const expanded = Object.entries(property.properties) - .filter(pProperty => pProperty[1].$Kind !== 'NavigationProperty') - .map(entryToProperty(property)) - properties.splice(i + 1, 0, ...expanded); - } - - return paths; - } - - function entryToProperty(parent) { - - return function (entry) { - const key = entry[0]; - const property = entry[1]; - const propertyType = property.$Type && modelElement(property.$Type); - - if (propertyType && propertyType.$Kind && propertyType.$Kind === 'ComplexType') { - return { - properties: propertiesOfStructuredType(propertyType), - path: `${parent.path}${key}/`, - typeRefChain: parent.typeRefChain.concat(property.$Type), - isComplex: true - } - } - - return { - properties: {}, - path: `${parent.path}${key}`, - typeRefChain: [], - isComplex: false, - } - }; - } - - /** - * Add parameter for query option $search - * @param {Array} parameters Array of parameters to augment - * @param {string} target Target container child of path - * @param {object} restrictions Navigation property restrictions of navigation segment - */ - function optionSearch(parameters, target, restrictions) { - const searchRestrictions = restrictions.SearchRestrictions || target && target[voc.Capabilities.SearchRestrictions] || {}; - - if (searchRestrictions.Searchable !== false) { - if (searchRestrictions[voc.Core.Description]) { - parameters.push({ - name: queryOptionPrefix + 'search', - description: searchRestrictions[voc.Core.Description], - in: 'query', - schema: { type: 'string' } - }); - } else { - parameters.push({ $ref: '#/components/parameters/search' }); - } - } - } - - /** - * Add parameter for query option $select - * @param {Array} parameters Array of parameters to augment - * @param {object} element Model element of navigation segment - * @param {string} target Target container child of path - * @param {object} restrictions Navigation property restrictions of navigation segment - */ - function optionSelect(parameters, element, target, restrictions) { - const selectSupport = restrictions.SelectSupport || target && target[voc.Capabilities.SelectSupport] || {}; - - if (selectSupport.Supported !== false) { - const type = modelElement(element.$Type) || {}; - const properties = propertiesOfStructuredType(type); - const selectItems = []; - Object.keys(properties).filter(key => properties[key].$Kind != 'NavigationProperty').forEach( - key => selectItems.push(key) - ) - if (selectItems.length > 0) { - parameters.push({ - name: queryOptionPrefix + 'select', - description: 'Select properties to be returned, see [Select](http://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part1-protocol.html#sec_SystemQueryOptionselect)', - in: 'query', - explode: false, - schema: { - type: 'array', - uniqueItems: true, - items: { - type: 'string', - enum: selectItems - } - } - }); - } - } - } - - /** - * Add parameter for query option $skip - * @param {Array} parameters Array of parameters to augment - * @param {string} target Target container child of path - * @param {object} restrictions Navigation property restrictions of navigation segment - */ - function optionSkip(parameters, target, restrictions) { - const supported = restrictions.SkipSupported !== undefined - ? restrictions.SkipSupported - : target == null || target[voc.Capabilities.SkipSupported] !== false; - - if (supported) { - parameters.push({ - $ref: '#/components/parameters/skip' - }); - } - } - - /** - * Add parameter for query option $top - * @param {Array} parameters Array of parameters to augment - * @param {string} target Target container child of path - * @param {object} restrictions Navigation property restrictions of navigation segment - */ - function optionTop(parameters, target, restrictions) { - const supported = restrictions.TopSupported !== undefined - ? restrictions.TopSupported - : target == null || target[voc.Capabilities.TopSupported] !== false; - - if (supported) { - parameters.push({ - $ref: '#/components/parameters/top' - }); - } - } - - /** - * Construct Operation Object for update - * @param {object} pathItem Path Item Object to augment - * @param {object} element Model element of navigation segment - * @param {string} name Name of navigation segment - * @param {string} sourceName Name of path source - * @param {string} target Target container child of path - * @param {integer} level Number of navigation segments so far - * @param {object} restrictions Navigation property restrictions of navigation segment - * @param {boolean} byKey Update by key - */ - function operationUpdate(pathItem, element, name, sourceName, target, level, restrictions, byKey) { - const updateRestrictions = restrictions.UpdateRestrictions || target && target[voc.Capabilities.UpdateRestrictions] || {}; - let countRestrictions = target && (target[voc.Capabilities.CountRestrictions]?.Countable === false); - if (updateRestrictions.Updatable !== false) { - const type = modelElement(element.$Type); - const operation = { - summary: updateRestrictions.Description || operationSummary('Changes', name, sourceName, level, element.$Collection, byKey), - tags: [sourceName], - requestBody: { - description: type && type[voc.Core.Description] || 'New property values', - required: true, - content: { - 'application/json': { - schema: ref(element.$Type, SUFFIX.update), - } - } - }, - responses: response(204, "Success", undefined, updateRestrictions.ErrorResponses, !countRestrictions), - }; - if (updateRestrictions.LongDescription) operation.description = updateRestrictions.LongDescription; - customParameters(operation, updateRestrictions); - const updateMethod = updateRestrictions.UpdateMethod ? updateRestrictions.UpdateMethod.toLowerCase() : "patch"; - pathItem[updateMethod] = operation; - } - } - - /** - * Construct Operation Object for delete - * @param {object} pathItem Path Item Object to augment - * @param {object} element Model element of navigation segment - * @param {string} name Name of navigation segment - * @param {string} sourceName Name of path source - * @param {string} target Target container child of path - * @param {integer} level Number of navigation segments so far - * @param {object} restrictions Navigation property restrictions of navigation segment - * @param {boolean} byKey Delete by key - */ - function operationDelete(pathItem, element, name, sourceName, target, level, restrictions, byKey) { - const deleteRestrictions = restrictions.DeleteRestrictions || target && target[voc.Capabilities.DeleteRestrictions] || {}; - let countRestrictions = target && (target[voc.Capabilities.CountRestrictions]?.Countable === false); - if (deleteRestrictions.Deletable !== false) { - pathItem.delete = { - summary: deleteRestrictions.Description || operationSummary('Deletes', name, sourceName, level, element.$Collection, byKey), - tags: [sourceName], - responses: response(204, "Success", undefined, deleteRestrictions.ErrorResponses, !countRestrictions), - }; - if (deleteRestrictions.LongDescription) pathItem.delete.description = deleteRestrictions.LongDescription; - customParameters(pathItem.delete, deleteRestrictions); - } - } - - /** - * Add paths and Path Item Objects for navigation segments - * @param {object} paths The Paths Object to augment - * @param {string} prefix Prefix for path - * @param {Array} prefixParameters Parameter Objects for prefix - * @param {object} type Entity type object of navigation segment - * @param {string} sourceName Name of path source - * @param {integer} level Number of navigation segments so far - * @param {string} navigationPrefix Path for finding navigation restrictions - */ - function pathItemsWithNavigation(paths, prefix, prefixParameters, type, root, sourceName, level, navigationPrefix) { - const navigationRestrictions = root[voc.Capabilities.NavigationRestrictions] || {}; - const rootNavigable = level == 0 && enumMember(navigationRestrictions.Navigability) != 'None' - || level == 1 && enumMember(navigationRestrictions.Navigability) != 'Single' - || level > 1; - - if (type && level < maxLevels) { - const properties = navigationPathMap(type); - Object.keys(properties).forEach(name => { - const parentRestrictions = navigationPropertyRestrictions(root, navigationPrefix); - if (enumMember(parentRestrictions.Navigability) == 'Single') return; - - const navigationPath = navigationPrefix + (navigationPrefix.length > 0 ? '/' : '') + name; - const restrictions = navigationPropertyRestrictions(root, navigationPath); - if (['Recursive', 'Single'].includes(enumMember(restrictions.Navigability)) - || restrictions.Navigability == null && rootNavigable) { - const targetSetName = root.$NavigationPropertyBinding && root.$NavigationPropertyBinding[navigationPath]; - const target = entityContainer[targetSetName]; - const targetType = target && modelElement(target.$Type); - const targetName = (targetType && targetType[voc.Common.Label]) || targetSetName; - pathItems(paths, prefix + '/' + name, prefixParameters, properties[name], root, sourceName, targetName, target, level + 1, navigationPath); - } - }); - } - } - - /** - * Collect navigation paths of a navigation segment and its potentially structured components - * @param {object} type Structured type - * @param {object} map Map of navigation property paths and their types - * @param {string} prefix Navigation prefix - * @param {integer} level Number of navigation segments so far - * @return {object} Map of navigation property paths and their types - */ - function navigationPathMap(type, map = {}, prefix = '', level = 0) { - const properties = propertiesOfStructuredType(type); - Object.keys(properties).forEach(key => { - if (properties[key].$Kind == 'NavigationProperty') { - map[prefix + key] = properties[key]; - } else if (properties[key].$Type && !properties[key].$Collection && level < maxLevels) { - navigationPathMap(modelElement(properties[key].$Type), map, prefix + key + '/', level + 1); - } - }) - return map; - } - - /** - * Construct map of key names for an entity type - * @param {object} type Entity type object - * @return {object} Map of key names - */ - function keyMap(type) { - const map = {}; - if (type.$Kind == 'EntityType') { - const keys = getKey(type) || []; - keys.forEach(key => { - if (typeof key == 'string') - map[key] = true; - }); - } - return map; - } - - /** - * Key for path item - * @param {object} entityType Entity Type object - * @return {array} Key of entity type or null - */ - function getKey(entityType) { - let type = entityType; - let keys = null; - while (type) { - keys = type.$Key; - if (keys || !type.$BaseType) break; - type = modelElement(type.$BaseType); - } - return keys; - } - - /** - * Key for path item - * @param {object} entityType Entity Type object - * @param {integer} level Number of navigation segments so far - * @return {object} key: Key segment, parameters: key parameters - */ - function entityKey(entityType, level) { - let segment = ''; - const params = []; - const keys = getKey(entityType) || []; - const properties = propertiesOfStructuredType(entityType); - - keys.forEach((key, index) => { - const suffix = level > 0 ? '_' + level : ''; - if (keyAsSegment) - segment += '/'; - else { - if (index > 0) segment += ','; - if (keys.length != 1) segment += key + '='; - } - let parameter; - let property = {}; - if (typeof key == 'string') { - parameter = key; - property = properties[key]; - } else { - parameter = Object.keys(key)[0]; - const segments = key[parameter].split('/'); - property = properties[segments[0]]; - for (let i = 1; i < segments.length; i++) { - const complexType = modelElement(property.$Type); - const properties = propertiesOfStructuredType(complexType); - property = properties[segments[i]]; - } - } - const propertyType = property.$Type; - segment += pathValuePrefix(propertyType) + '{' + parameter + suffix + '}' + pathValueSuffix(propertyType); - const param = { - description: [property[voc.Core.Description], property[voc.Core.LongDescription]].filter(t => t).join(' \n') - || 'key: ' + parameter, - in: 'path', - name: parameter + suffix, - required: true, - schema: getSchema(property, '', true) - }; - params.push(param); - }) - return { segment: (keyAsSegment ? '' : '(') + segment + (keyAsSegment ? '' : ')'), parameters: params }; - } - - /** - * Prefix for key value in key segment - * @param {typename} Qualified name of key property type - * @return {string} value prefix - */ - function pathValuePrefix(typename) { - //TODO: handle other Edm types, enumeration types, and type definitions - if (['Edm.Int64', 'Edm.Int32', 'Edm.Int16', 'Edm.SByte', 'Edm.Byte', - 'Edm.Double', 'Edm.Single', 'Edm.Date', 'Edm.DateTimeOffset', 'Edm.Guid'].includes(typename)) return ''; - if (keyAsSegment) return ''; - return `'`; - } - - /** - * Suffix for key value in key segment - * @param {typename} Qualified name of key property type - * @return {string} value prefix - */ - function pathValueSuffix(typename) { - //TODO: handle other Edm types, enumeration types, and type definitions - if (['Edm.Int64', 'Edm.Int32', 'Edm.Int16', 'Edm.SByte', 'Edm.Byte', - 'Edm.Double', 'Edm.Single', 'Edm.Date', 'Edm.DateTimeOffset', 'Edm.Guid'].includes(typename)) return ''; - if (keyAsSegment) return ''; - return `'`; - } - - /** - * Add path and Path Item Object for actions and functions bound to the element - * @param {object} paths Paths Object to augment - * @param {string} prefix Prefix for path - * @param {Array} prefixParameters Parameter Objects for prefix - * @param {object} element Model element the operations are bound to - * @param {string} sourceName Name of path source - * @param {boolean} byKey read by key - */ - function pathItemsForBoundOperations(paths, prefix, prefixParameters, element, sourceName, byKey = false) { - //ignore operations on navigation path - if (element.$Kind === "NavigationProperty") { - return; - } - const overloads = boundOverloads[element.$Type + (!byKey && element.$Collection ? '-c' : '')] || []; - overloads.forEach(item => { - if (item.overload.$Kind == 'Action') - pathItemAction(paths, prefix + '/' + item.name, prefixParameters, item.name, item.overload, sourceName); - else - pathItemFunction(paths, prefix + '/' + item.name, prefixParameters, item.name, item.overload, sourceName); - }); - } - - /** - * Add path and Path Item Object for an action import - * @param {object} paths Paths Object to augment - * @param {string} name Name of action import - * @param {object} child Action import object - */ - function pathItemActionImport(paths, name, child) { - const overload = modelElement(child.$Action).find(pOverload => !pOverload.$IsBound); - pathItemAction(paths, '/' + name, [], child.$Action, overload, child.$EntitySet, child); - } - - /** - * Add path and Path Item Object for action overload - * @param {object} paths Paths Object to augment - * @param {string} prefix Prefix for path - * @param {Array} prefixParameters Parameter Objects for prefix - * @param {string} actionName Qualified name of function - * @param {object} overload Function overload - * @param {string} sourceName Name of path source - * @param {string} actionImport Action import - */ - function pathItemAction(paths, prefix, prefixParameters, actionName, overload, sourceName, actionImport = {}) { - const name = actionName.indexOf('.') === -1 ? actionName : nameParts(actionName).name; - const pathItem = { - post: { - summary: actionImport[voc.Core.Description] || overload[voc.Core.Description] || 'Invokes action ' + name, - tags: [overload[voc.Common.Label] || sourceName || 'Service Operations'], - responses: overload.$ReturnType ? response(200, "Success", overload.$ReturnType, overload[voc.Capabilities.OperationRestrictions]?.ErrorResponses) - : response(204, "Success", undefined, overload[voc.Capabilities.OperationRestrictions]?.ErrorResponses), - } - }; - const actionExtension = getExtensions(overload, 'operation'); - if (Object.keys(actionExtension).length > 0) { - Object.assign(pathItem.post, actionExtension); - } - const description = actionImport[voc.Core.LongDescription] || overload[voc.Core.LongDescription]; - if (description) pathItem.post.description = description; - if (prefixParameters.length > 0) pathItem.post.parameters = [...prefixParameters]; - let parameters = overload.$Parameter || []; - if (overload.$IsBound) parameters = parameters.slice(1); - if (parameters.length > 0) { - const requestProperties = {}; - parameters.forEach(p => { requestProperties[p.$Name] = getSchema(p) }); - pathItem.post.requestBody = { - description: 'Action parameters', - content: { - 'application/json': { - schema: { - type: 'object', - properties: requestProperties - } - } - } - } - } - customParameters(pathItem.post, overload[voc.Capabilities.OperationRestrictions] || {}); - paths[prefix] = pathItem; - } - - /** - * Add path and Path Item Object for an action import - * @param {object} paths Paths Object to augment - * @param {string} name Name of function import - * @param {object} child Function import object - */ - function pathItemFunctionImport(paths, name, child) { - const overloads = modelElement(child.$Function); - console.assert(overloads, 'Unknown function "' + child.$Function + '" in function import "' + name + '"'); - overloads && overloads.filter(overload => !overload.$IsBound).forEach(overload => pathItemFunction(paths, '/' + name, [], child.$Function, overload, child.$EntitySet, child)); - } - - /** - * Add path and Path Item Object for function overload - * @param {object} paths Paths Object to augment - * @param {string} prefix Prefix for path - * @param {Array} prefixParameters Parameter Objects for prefix - * @param {string} functionName Qualified name of function - * @param {object} overload Function overload - * @param {string} sourceName Name of path source - * @param {object} functionImport Function Import - */ - function pathItemFunction(paths, prefix, prefixParameters, functionName, overload, sourceName, functionImport = {}) { - const name = functionName.indexOf('.') === -1 ? functionName : nameParts(functionName).name; - let parameters = overload.$Parameter || []; - if (overload.$IsBound) parameters = parameters.slice(1); - const pathSegments = []; - const params = []; - - const implicitAliases = csdl.$Version > '4.0' || parameters.some(p => p[voc.Core.OptionalParameter]); - - parameters.forEach(p => { - const param = { - required: implicitAliases ? !p[voc.Core.OptionalParameter] : true - }; - const description = [p[voc.Core.Description], p[voc.Core.LongDescription]].filter(t => t).join(' \n'); - if (description) param.description = description; - const type = modelElement(p.$Type || 'Edm.String'); - // TODO: check whether parameter or type definition of Edm.Stream is annotated with JSON.Schema - if (p.$Collection || p.$Type == 'Edm.Stream' - || type && ['ComplexType', 'EntityType'].includes(type.$Kind) - || type && type.$UnderlyingType == 'Edm.Stream') { - param.in = 'query'; - if ( - implicitAliases && - csdl.$Version !== '2.0' && - SYSTEM_QUERY_OPTIONS.includes(p.$Name.toLowerCase()) - ) { - param.name = '@' + p.$Name; - } else if (implicitAliases) { - param.name = p.$Name; - } else { - pathSegments.push(p.$Name + '=@' + p.$Name); - param.name = '@' + p.$Name; - } - param.schema = { type: 'string' }; - if (description) param.description += ' \n'; else param.description = ''; - param.description += 'This is ' - + (p.$Collection ? 'a ' : '') - + 'URL-encoded JSON ' - + (p.$Collection ? 'array with items ' : '') - + 'of type ' - + namespaceQualifiedName(p.$Type || 'Edm.String') - + ', see [Complex and Collection Literals](https://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part2-url-conventions.html#sec_ComplexandCollectionLiterals)'; - param.example = p.$Collection ? '[]' : '{}'; - } else { - if (implicitAliases) { - param.in = 'query'; - } else { - pathSegments.push(p.$Name + "={" + p.$Name + "}"); - param.in = 'path'; - } - if ( - implicitAliases && - csdl.$Version !== '2.0' && - SYSTEM_QUERY_OPTIONS.includes(p.$Name.toLowerCase()) - ) - param.name = '@' + p.$Name; - else - param.name = p.$Name; - if (!p.$Type || p.$Type === "Edm.String" || (type && (!type.$Type || type.$Type === "Edm.String"))) { - if (description) param.description += " \n"; - else param.description = ""; - param.description += "String value needs to be enclosed in single quotes"; - } - param.schema = getSchema(p, '', true, true); - } - params.push(param); - }); - - const pathParameters = implicitAliases ? '' : '(' + pathSegments.join(',') + ')'; - const pathItem = { - get: { - summary: functionImport[voc.Core.Description] || overload[voc.Core.Description] || 'Invokes function ' + name, - tags: [overload[voc.Common.Label] || sourceName || 'Service Operations'], - parameters: prefixParameters.concat(params), - responses: response(200, "Success", overload.$ReturnType, overload[voc.Capabilities.OperationRestrictions]?.ErrorResponses), - } - }; - const functionExtension = getExtensions(overload, 'operation'); - if (Object.keys(functionExtension).length > 0) { - Object.assign(pathItem.get, functionExtension); - } - const iDescription = functionImport[voc.Core.LongDescription] || overload[voc.Core.LongDescription]; - if (iDescription) pathItem.get.description = iDescription; - customParameters(pathItem.get, overload[voc.Capabilities.OperationRestrictions] || {}); - paths[prefix + pathParameters] = pathItem; - } - - /** - * Add path and Path Item Object for batch requests - * @param {object} paths Paths Object to augment - * @param {object} container Entity container - */ - function pathItemBatch(paths, container) { - const batchSupport = container[voc.Capabilities.BatchSupport] || {}; - const supported = container[voc.Capabilities.BatchSupported] !== false && batchSupport.Supported !== false; - if (supported) { - const firstEntitySet = Object.keys(container).filter(child => isIdentifier(child) && container[child].$Collection)[0]; - paths['/$batch'] = { - post: { - summary: batchSupport[voc.Core.Description] || 'Sends a group of requests', - description: (batchSupport[voc.Core.LongDescription] || 'Group multiple requests into a single request payload, see ' - + '[Batch Requests](http://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part1-protocol.html#sec_BatchRequests).') - + '\n\n*Please note that "Try it out" is not supported for this request.*', - tags: ['Batch Requests'], - requestBody: { - required: true, - description: 'Batch request', - content: { - 'multipart/mixed;boundary=request-separator': { - schema: { - type: 'string' - }, - example: '--request-separator\n' - + 'Content-Type: application/http\n' - + 'Content-Transfer-Encoding: binary\n\n' - + 'GET ' + firstEntitySet + ' HTTP/1.1\n' - + 'Accept: application/json\n\n' - + '\n--request-separator--' - } - } - }, - responses: { - '4XX': { - $ref: '#/components/responses/error' - } - } - } - }; - paths['/$batch'].post.responses[csdl.$Version < '4.0' ? 202 : 200] = { - description: 'Batch response', - content: { - 'multipart/mixed': { - schema: { - type: 'string' - }, - example: '--response-separator\n' - + 'Content-Type: application/http\n\n' - + 'HTTP/1.1 200 OK\n' - + 'Content-Type: application/json\n\n' - + '{...}' - + '\n--response-separator--' - } - } - }; - } - } - - /** - * Construct Responses Object - * @param {string} code HTTP response code - * @param {string} description Description - * @param {object} type Response type object - * @param {array} errors Array of operation-specific status codes with descriptions - */ - function response(code, description, type, errors, isCount = true) { - const r = {}; - r[code] = { - description: description - }; - let CountPropertyObj = { [csdl.$Version > '4.0' ? '@count' : '@odata.count']: ref('count') }; - if (code != 204) { - const s = getSchema(type); - r[code].content = { - 'application/json': {} - }; - - if (type.$Collection) { - r[code].content['application/json'].schema = { - type: 'object', - title: 'Collection of ' + nameParts(type.$Type ? type.$Type : 'Edm.String').name, - properties: { - ...(isCount && CountPropertyObj), - value: s - } - }; - } - - else if ( - type.$Type === undefined || - (type.$Type.startsWith("Edm.") && - !["Edm.Stream", "Edm.EntityType", "Edm.ComplexType"].includes( - type.$Type, - )) - ) { - r[code].content['application/json'].schema = { type: "object", properties: { value: s } }; - } - - else { - r[code].content['application/json'].schema = s; - } - } - if (errors) { - for (const e of errors) { - r[e.StatusCode] = { - description: e.Description, - content: { - "application/json": { - schema: { $ref: "#/components/schemas/error" }, - }, - }, - }; - } - } else { - r["4XX"] = { - $ref: "#/components/responses/error", - }; - } - return r; - } - - /** - * Construct the Components Object from the types of the CSDL document - * @param {object} csdl CSDL document - * @param {object} entityContainer Entity Container object - * @return {object} Components Object - */ - function getComponents(csdl, entityContainer) { - const c = { - schemas: getSchemas(csdl) - }; - - if (csdl.$EntityContainer) { - c.parameters = getParameters(); - c.responses = { - error: { - description: 'Error', - content: { - 'application/json': { - schema: ref('error') - } - } - } - }; - } - - getSecuritySchemes(c, entityContainer) - - return c; - } - - /** - * Construct Schema Objects from the types of the CSDL document - * @param {object} csdl CSDL document - * @return {object} Map of Schema Objects - */ - function getSchemas(csdl) { - const unordered = {}; - - for (const r of requiredSchemas.list) { - const type = modelElement(`${r.namespace}.${r.name}`); - if (!type) continue; - switch (type.$Kind) { - case "ComplexType": - case "EntityType": - schemasForStructuredType(unordered, r.namespace, r.name, type, r.suffix); - break; - case "EnumType": - schemaForEnumerationType(unordered, r.namespace, r.name, type); - break; - case "TypeDefinition": - schemaForTypeDefinition(unordered, r.namespace, r.name, type); - break; - } - } - - // Add @OpenAPI.Extensions at entity level to schema object - Object.keys(csdl).filter(name => isIdentifier(name)).forEach(namespace => { - const schema = csdl[namespace]; - Object.keys(schema).filter(name => isIdentifier(name)).forEach(name => { - const type = schema[name]; - if (type.$Kind === 'EntityType' || type.$Kind === 'ComplexType') { - const schemaName = namespace + "." + name + SUFFIX.read; - const extensions = getExtensions(type, 'schema'); - if (Object.keys(extensions).length > 0) { - unordered[schemaName] = unordered[schemaName] || {}; - Object.assign(unordered[schemaName], extensions); - } - } - }); - }); - - const ordered = {}; - for (const name of Object.keys(unordered).sort()) { - ordered[name] = unordered[name]; - } - - inlineTypes(ordered); - - if (csdl.$EntityContainer) { - ordered.count = count(); - ordered.error = error(); - } - - return ordered; - } - - /** - * Construct Schema Objects from the types of the CSDL document - * @param {object} schemas Map of Schema Objects to augment - */ - function inlineTypes(schemas) { - if (typesToInline.geoPoint) { - schemas.geoPoint = { - type: 'object', - properties: { - coordinates: ref('geoPosition'), - type: { - type: 'string', - enum: ['Point'], - default: 'Point' - } - }, - required: ['type', 'coordinates'] - }; - schemas.geoPosition = { - type: 'array', - minItems: 2, - items: { - type: 'number' - } - } - } - } - - /** - * Construct Schema Objects for an enumeration type - * @param {object} schemas Map of Schema Objects to augment - * @param {string} qualifier Qualifier for structured type - * @param {string} name Simple name of structured type - * @param {object} type Structured type - * @return {object} Map of Schemas Objects - */ - function schemaForEnumerationType(schemas, qualifier, name, type) { - const members = []; - Object.keys(type).filter(iName => isIdentifier(iName)).forEach(iName2 => { - members.push(iName2); - }); - - const s = { - type: 'string', - title: name, - enum: members - }; - const description = type[voc.Core.LongDescription]; - if (description) s.description = description; - schemas[qualifier + '.' + name] = s; - } - - /** - * Construct Schema Objects for a type definition - * @param {object} schemas Map of Schema Objects to augment - * @param {string} qualifier Qualifier for structured type - * @param {string} name Simple name of structured type - * @param {object} type Structured type - * @return {object} Map of Schemas Objects - */ - function schemaForTypeDefinition(schemas, qualifier, name, type) { - const s = getSchema(Object.assign({ $Type: type.$UnderlyingType }, type)); - s.title = name; - const description = type[voc.Core.LongDescription]; - if (description) s.description = description; - schemas[qualifier + '.' + name] = s; - } - - /** - * Construct Schema Objects for a structured type - * @param {object} schemas Map of Schema Objects to augment - * @param {string} qualifier Qualifier for structured type - * @param {string} name Simple name of structured type - * @param {string} suffix Suffix for read/create/update - * @param {object} type Structured type - * @return {object} Map of Schemas Objects - */ - function schemasForStructuredType(schemas, qualifier, name, type, suffix) { - const schemaName = qualifier + "." + name + suffix; - const baseName = qualifier + "." + name; - const isKey = keyMap(type); - const required = Object.keys(isKey); - const schemaProperties = {}; - let isCount = true; - if (csdl[qualifier]?.$Annotations) { - const annotations = csdl[qualifier].$Annotations[`${qualifier}.EntityContainer/${name}`]; - if (annotations && annotations[voc.Capabilities.CountRestrictions] && annotations[voc.Capabilities.CountRestrictions]?.Countable === false) { - isCount = false; - } - } - const properties = propertiesOfStructuredType(type); - Object.keys(properties).forEach(iName => { - const property = properties[iName]; - if (suffix === SUFFIX.read) schemaProperties[iName] = getSchema(property); - if ((Object.prototype.hasOwnProperty.call(property, '@Common.FieldControl')) && property['@Common.FieldControl'] === 'Mandatory') { required.push(iName) } - if (property.$Kind == 'NavigationProperty') { - if (property.$Collection && suffix === "" && isCount === true) { - schemaProperties[`${iName}@${csdl.$Version === '4.0' ? 'odata.' : ''}count`] = ref('count'); - } - if (property[voc.Core.Permissions] != "Read" && !property[voc.Core.Computed] && (property.$ContainsTarget || property.$OnDelete === 'Cascade')) { - if (suffix === SUFFIX.create) - schemaProperties[iName] = getSchema(property, SUFFIX.create); - if (suffix === SUFFIX.update) - schemaProperties[iName] = getSchema(property, SUFFIX.create); - } - } else { - if (property[voc.Core.Permissions] === "Read" || property[voc.Core.Computed] || property[voc.Core.ComputedDefaultValue]) { - let index = required.indexOf(iName); - if (index != -1) required.splice(index, 1); - } - if (!(property[voc.Core.Permissions] === "Read" || property[voc.Core.Computed])) { - if (suffix === SUFFIX.create) - schemaProperties[iName] = getSchema(property, SUFFIX.create); - if (suffix === SUFFIX.update && !isKey[iName] && !property[voc.Core.Immutable]) - schemaProperties[iName] = getSchema(property, SUFFIX.update); - } - } - }); - - - schemas[schemaName] = { - title: (type[voc.Core.Description] || name) + TITLE_SUFFIX[suffix], - type: 'object' - }; - if (Object.keys(schemaProperties).length > 0) - schemas[schemaName].properties = schemaProperties; - - if (suffix === SUFFIX.read && type["@ODM.root"]) schemas[schemaName]["x-sap-root-entity"] = type["@ODM.root"] - odmExtensions(type, schemas[schemaName]); - erExtensions(type, schemas[schemaName]); - - if (suffix === SUFFIX.create && required.length > 0) - schemas[schemaName].required = [...new Set(required)]; - - const description = type[voc.Core.LongDescription]; - if (description) { - schemas[schemaName].description = description; - } - - if (derivedTypes[baseName]) { - schemas[schemaName].anyOf = []; - derivedTypes[baseName].forEach((derivedType) => { - schemas[schemaName].anyOf.push(ref(derivedType, suffix)); - }); - if (!type.$Abstract) schemas[schemaName].anyOf.push({}); - } - } - - /** - * Add ODM extensions to OpenAPI schema for a structured type - * @param {object} type Structured type - * @param {object} schema OpenAPI schema to augment - */ - function odmExtensions(type, schema) { - for (const [annotation, openApiExtension] of Object.entries(ODM_ANNOTATIONS)) { - if (type[annotation]) schema[openApiExtension] = type[annotation]; - } - } - - /** - * Add entity relationship extensions to OpenAPI schema for a structured type - * @param {object} type Structured type - * @param {object} schema OpenAPI schema to augment - */ - function erExtensions(type, schema) { - for (const [annotation, openApiExtension] of Object.entries(ER_ANNOTATIONS)) { - if (type[annotation]) schema[openApiExtension] = type[annotation]; - } - } - - /** - * Collect all properties of a structured type along the inheritance hierarchy - * @param {object} type Structured type - * @return {object} Map of properties - */ - function propertiesOfStructuredType(type) { - const properties = (type && type.$BaseType) ? propertiesOfStructuredType(modelElement(type.$BaseType)) : {}; - if (type) { - Object.keys(type).filter(name => isIdentifier(name)).forEach(name => { - properties[name] = type[name]; - }); - } - return properties; - } - - /** - * Construct Parameter Objects for type-independent OData system query options - * @return {object} Map of Parameter Objects - */ - function getParameters() { - const param = { - top: { - name: queryOptionPrefix + 'top', - in: 'query', - description: 'Show only the first n items, see [Paging - Top](http://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part1-protocol.html#sec_SystemQueryOptiontop)', - schema: { - type: 'integer', - minimum: 0 - }, - example: 50 - }, - skip: { - name: queryOptionPrefix + 'skip', - in: 'query', - description: 'Skip the first n items, see [Paging - Skip](http://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part1-protocol.html#sec_SystemQueryOptionskip)', - schema: { - type: 'integer', - minimum: 0 - } - }, - count: { - name: queryOptionPrefix + 'count', - in: 'query', - description: 'Include count of items, see [Count](http://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part1-protocol.html#sec_SystemQueryOptioncount)', - schema: { - type: 'boolean' - } - } - }; - - if (csdl.$Version >= '4.0') param.search = { - name: queryOptionPrefix + 'search', - in: 'query', - description: 'Search items by search phrases, see [Searching](http://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part1-protocol.html#sec_SystemQueryOptionsearch)', - schema: { - type: 'string' - } - }; - - return param; - } - - /** - * Construct OData error response - * @return {object} Error response schema - */ - function error() { - const err = { - type: 'object', - required: ['error'], - properties: { - error: { - type: 'object', - required: ['code', 'message'], - properties: { - code: { type: 'string' }, - message: { type: 'string' }, - target: { type: 'string' }, - details: { - type: 'array', - items: { - type: 'object', - required: ['code', 'message'], - properties: { - code: { type: 'string' }, - message: { type: 'string' }, - target: { type: 'string' } - } - } - }, - innererror: { - type: 'object', - description: 'The structure of this object is service-specific' - } - } - } - } - }; - - if (csdl.$Version < '4.0') { - err.properties.error.properties.message = { - type: 'object', - properties: { - lang: { type: 'string' }, - value: { type: 'string' } - }, - required: ['lang', 'value'] - }; - delete err.properties.error.properties.details; - delete err.properties.error.properties.target; - } - - return err; - } - - /** - * Construct OData count response - * @return {object} Count response schema - */ - function count() { - return { - anyOf: [ - { type: 'number' }, - { type: 'string' } - ], - description: 'The number of entities in the collection. Available when using the [$count](http://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part1-protocol.html#sec_SystemQueryOptioncount) query option.', - }; - } - - /** - * Construct Schema Object for model object referencing a type - * @param {object} modelElement referencing a type - * @return {object} Schema Object - */ - function getSchema(element, suffix = '', forParameter = false, forFunction = false) { - let s = {}; - switch (element.$Type) { - case 'Edm.AnnotationPath': - case 'Edm.ModelElementPath': - case 'Edm.NavigationPropertyPath': - case 'Edm.PropertyPath': - s.type = 'string'; - break; - case 'Edm.Binary': - s = { - type: 'string', - format: 'base64url' - }; - if (element.$MaxLength) s.maxLength = Math.ceil(4 * element.$MaxLength / 3); - break; - case 'Edm.Boolean': - s.type = 'boolean'; - break; - case 'Edm.Byte': - s = { - type: 'integer', - format: 'uint8' - }; - break; - case 'Edm.Date': - s = { - type: 'string', - format: 'date', - example: '2017-04-13' - }; - break; - case 'Edm.DateTime': - case 'Edm.DateTimeOffset': - s = { - type: 'string', - format: 'date-time', - example: '2017-04-13T15:51:04' + (isNaN(element.$Precision) || element.$Precision === 0 ? '' : '.' + '0'.repeat(element.$Precision)) + 'Z' - }; - break; - case 'Edm.Decimal': - s = { - anyOf: [{ type: 'number', format: 'decimal' }, { type: 'string' }], - example: 0 - }; - if (!isNaN(element.$Precision)) s['x-sap-precision'] = element.$Precision; - if (!isNaN(element.$Scale)) s['x-sap-scale'] = element.$Scale; - // eslint-disable-next-line no-case-declarations - let scale = !isNaN(element.$Scale) ? element.$Scale : null; - if (scale !== null) { - // Node.js 12.13.0 has problems with negative exponents, 10 ** -5 --> 0.000009999999999999999 - if (scale <= 0) - s.anyOf[0].multipleOf = 10 ** -scale; - else - s.anyOf[0].multipleOf = 1 / 10 ** scale; - } - if (element.$Precision < 16) { - let limit = 10 ** (element.$Precision - scale); - let delta = 10 ** -scale; - s.anyOf[0].maximum = limit - delta; - s.anyOf[0].minimum = -s.anyOf[0].maximum; - } - break; - case 'Edm.Double': - s = { - anyOf: [{ type: 'number', format: 'double' }, { type: 'string' }], - example: 3.14 - }; - break; - case 'Edm.Duration': - s = { - type: 'string', - format: 'duration', - example: 'P4DT15H51M04S' - }; - break; - case 'Edm.GeographyPoint': - case 'Edm.GeometryPoint': - s = ref('geoPoint'); - typesToInline.geoPoint = true; - break; - case 'Edm.Guid': - s = { - type: 'string', - format: 'uuid', - example: '01234567-89ab-cdef-0123-456789abcdef' - }; - break; - case 'Edm.Int16': - s = { - type: 'integer', - format: 'int16' - }; - break; - case 'Edm.Int32': - s = { - type: 'integer', - format: 'int32' - }; - break; - case 'Edm.Int64': - s = { - anyOf: [{ type: 'integer', format: 'int64' }, { type: 'string' }], - example: "42" - }; - break; - case 'Edm.PrimitiveType': - s = { - anyOf: [{ type: 'boolean' }, { type: 'number' }, { type: 'string' }] - }; - break; - case 'Edm.SByte': - s = { - type: 'integer', - format: 'int8' - }; - break; - case 'Edm.Single': - s = { - anyOf: [{ type: 'number', format: 'float' }, { type: 'string' }], - example: 3.14 - }; - break; - case 'Edm.Stream': - // eslint-disable-next-line no-case-declarations - let jsonSchema = element[voc.JSON.Schema]; - if (jsonSchema) { - if (typeof jsonSchema == 'string') - s = JSON.parse(jsonSchema); - else - s = jsonSchema; - } else { - s = { - type: 'string', - format: 'base64url' - }; - } - break; - case 'Edm.String': - case undefined: - s.type = 'string'; - if (element.$MaxLength) s.maxLength = element.$MaxLength; - getPattern(s, element); - break; - case 'Edm.TimeOfDay': - s = { - type: 'string', - format: 'time', - example: '15:51:04' - }; - break; - default: - if (element.$Type.startsWith('Edm.')) { - DEBUG?.('Unknown type: ' + element.$Type); - } else { - let type = modelElement(element.$Type); - let isStructured = type && ['ComplexType', 'EntityType'].includes(type.$Kind); - s = ref(element.$Type, (isStructured ? suffix : '')); - if (element.$MaxLength) { - s = { - allOf: [s], - maxLength: element.$MaxLength - }; - } - } - } - - allowedValues(s, element); - - if (element.$Nullable) { - if (s.$ref) s = { allOf: [s] }; - s.nullable = true; - } - - if (element.$DefaultValue !== undefined) { - if (s.$ref) s = { allOf: [s] }; - s.default = element.$DefaultValue; - } - - if (element[voc.Core.Example]) { - if (s.$ref) s = { allOf: [s] }; - s.example = element[voc.Core.Example].Value; - } - - if (forFunction) { - if (s.example && typeof s.example === "string") { - s.example = `${pathValuePrefix(element.$Type)}${s.example - }${pathValueSuffix(element.$Type)} `; - } - if (s.pattern) { - const pre = pathValuePrefix(element.$Type); - const suf = pathValueSuffix(element.$Type); - s.pattern = s.pattern.replace(/^\^/, `^ ${pre} (`); - s.pattern = s.pattern.replace(/\$$/, `)${suf} $`); - } else if (!element.$Type || element.$Type === "Edm.String") { - s.pattern = "^'([^']|'')*'$"; - } - if (element.$Nullable) { - s.default = "null"; - if (s.pattern) { - s.pattern = s.pattern.replace(/^\^/, "^(null|"); - s.pattern = s.pattern.replace(/\$$/, ")$"); - } - } - } - - if (element[voc.Validation.Maximum] != undefined) { - if (s.$ref) s = { allOf: [s] }; - if (s.anyOf) { - s.anyOf[0].maximum = element[voc.Validation.Maximum]; - } - if (element[voc.Validation.Maximum + voc.Validation.Exclusive]) s.exclusiveMaximum = true; - } - - if (element[voc.Validation.Minimum] != undefined) { - if (s.$ref) s = { allOf: [s] }; - if (s.anyOf) { - s.anyOf[0].minimum = element[voc.Validation.Minimum]; - } - if (element[voc.Validation.Minimum + voc.Validation.Exclusive]) s.exclusiveMinimum = true; - } - - if (element.$Collection) { - s = { - type: 'array', - items: s - }; - } - - if (!forParameter && element[voc.Core.LongDescription]) { - if (s.$ref) s = { allOf: [s] }; - s.description = element[voc.Core.LongDescription]; - } - - if (element['@ODM.oidReference']?.entityName) { - s['x-sap-odm-oid-reference-entity-name'] = element['@ODM.oidReference'].entityName - } - - for (const key in element) { - if (key.startsWith(ER_ANNOTATION_PREFIX) && ER_ANNOTATIONS[key]) { - s[ER_ANNOTATIONS[key]] = element[key]; - } - } - return s; - } - - /** - * Add allowed values enum to Schema Object for string-like model element - * @param {object} schema Schema Object to augment - * @param {object} element Model element - */ - function allowedValues(schema, element) { - const values = element[voc.Validation.AllowedValues]; - if (values) schema.enum = values.map(record => record.Value); - } - - /** - * Add pattern to Schema Object for string-like model element - * @param {object} schema Schema Object to augment - * @param {object} element Model element - */ - function getPattern(schema, element) { - const pattern = element[voc.Validation.Pattern]; - if (pattern) schema.pattern = pattern; - } - - /** - * Construct Reference Object for a type - * @param {string} typename Qualified name of referenced type - * @param {string} suffix Optional suffix for referenced schema - * @return {object} Reference Object - */ - function ref(typename, suffix = '') { - let name = typename; - let nsp = ''; - let url = ''; - if (typename.indexOf('.') != -1) { - let parts = nameParts(typename); - nsp = namespace[parts.qualifier]; - name = nsp + '.' + parts.name; - url = namespaceUrl[nsp] || ''; - if (url === "" && !requiredSchemas.used[name + suffix]) { - requiredSchemas.used[name + suffix] = true; - requiredSchemas.list.push({ namespace: nsp, name: parts.name, suffix }); - } - //TODO: introduce better way than guessing - if (url.endsWith('.xml')) url = url.substring(0, url.length - 3) + "openapi3.json"; - } - return { - $ref: url + '#/components/schemas/' + name + suffix - }; - } - - /** - * Augment Components Object with map of Security Scheme Objects - * @param {object} components Components Object to augment - * @param {object} entityContainer Entity Container object - */ - function getSecuritySchemes(components, entityContainer) { - const authorizations = entityContainer && entityContainer[voc.Authorization.Authorizations] ? entityContainer[voc.Authorization.Authorizations] : []; - const schemes = {}; - const location = { Header: 'header', QueryOption: 'query', Cookie: 'cookie' }; - authorizations.forEach(auth => { - const scheme = {}; - const flow = {}; - if (auth.Description) scheme.description = auth.Description; - const qualifiedType = auth['@type'] || auth['@odata.type'] - const type = qualifiedType.substring(qualifiedType.lastIndexOf(".") + 1); - let unknown = false - switch (type) { - case 'ApiKey': - scheme.type = 'apiKey'; - scheme.name = auth.KeyName; - scheme.in = location[auth.Location]; - break; - case 'Http': - scheme.type = 'http'; - scheme.scheme = auth.Scheme; - scheme.bearerFormat = auth.BearerFormat; - break; - case 'OAuth2AuthCode': - scheme.type = 'oauth2'; - scheme.flows = { authorizationCode: flow }; - flow.authorizationUrl = auth.AuthorizationUrl; - flow.tokenUrl = auth.TokenUrl; - if (auth.RefreshUrl) flow.refreshUrl = auth.RefreshUrl; - flow.scopes = getScopes(auth); - break; - case 'OAuth2ClientCredentials': - scheme.type = 'oauth2'; - scheme.flows = { clientCredentials: flow }; - flow.tokenUrl = auth.TokenUrl; - if (auth.RefreshUrl) flow.refreshUrl = auth.RefreshUrl; - flow.scopes = getScopes(auth); - break; - case 'OAuth2Implicit': - scheme.type = 'oauth2'; - scheme.flows = { implicit: flow }; - flow.authorizationUrl = auth.AuthorizationUrl; - if (auth.RefreshUrl) flow.refreshUrl = auth.RefreshUrl; - flow.scopes = getScopes(auth); - break; - case 'OAuth2Password': - scheme.type = 'oauth2'; - scheme.flows = {}; - scheme.flows = { password: flow }; - flow.tokenUrl = auth.TokenUrl; - if (auth.RefreshUrl) flow.refreshUrl = auth.RefreshUrl; - flow.scopes = getScopes(auth); - break; - case 'OpenIDConnect': - scheme.type = 'openIdConnect'; - scheme.openIdConnectUrl = auth.IssuerUrl; - break; - default: - unknown = true - DEBUG?.('Unknown Authorization type ' + qualifiedType); - } - if (!unknown) schemes[auth.Name] = scheme; - }); - if (Object.keys(schemes).length > 0) components.securitySchemes = schemes - } - - function getScopes(authorization) { - const scopes = {}; - authorization.Scopes.forEach(scope => { scopes[scope.Scope] = scope.Description }); - return scopes; - } - - /** - * Augment OpenAPI document with Security Requirements Object - * @param {object} openapi OpenAPI document to augment - * @param {object} entityContainer Entity Container object - */ - function security(openapi, entityContainer) { - const securitySchemes = entityContainer && entityContainer[voc.Authorization.SecuritySchemes] ? entityContainer[voc.Authorization.SecuritySchemes] : []; - // check if securitySchemas exist if it does not exist then throw a warning - if (securitySchemes.length === 0) { - DEBUG?.('No security schemes defined in the entity container'); - } - if (securitySchemes.length > 0) openapi.security = []; - securitySchemes.forEach(scheme => { - const s = {}; - s[scheme.Authorization] = scheme.RequiredScopes || []; - openapi.security.push(s); - }); - } - - /** - * a qualified name consists of a namespace or alias, a dot, and a simple name - * @param {string} qualifiedName - * @return {string} namespace-qualified name - */ - function namespaceQualifiedName(qualifiedName) { - let np = nameParts(qualifiedName); - return namespace[np.qualifier] + '.' + np.name; - } - - /** - * a qualified name consists of a namespace or alias, a dot, and a simple name - * @param {string} qualifiedName - * @return {object} with components qualifier and name - */ - function nameParts(qualifiedName) { - const pos = qualifiedName.lastIndexOf('.'); - console.assert(pos > 0, 'Invalid qualified name ' + qualifiedName); - return { - qualifier: qualifiedName.substring(0, pos), - name: qualifiedName.substring(pos + 1) - }; - } - - /** - * an identifier does not start with $ and does not contain @ - * @param {string} name - * @return {boolean} name is an identifier - */ - function isIdentifier(name) { - return !name.startsWith('$') && !name.includes('@'); - } - -}; diff --git a/lib/compile/csdl2openapi.js b/lib/compile/csdl2openapi.js index c8aeeda..ea4d13b 100644 --- a/lib/compile/csdl2openapi.js +++ b/lib/compile/csdl2openapi.js @@ -64,6 +64,1450 @@ const { // Import constants from the constants module const { SUFFIX, TITLE_SUFFIX, SYSTEM_QUERY_OPTIONS, ODM_ANNOTATIONS, ER_ANNOTATION_PREFIX, ER_ANNOTATIONS } = constants; + +/** + * Construct an OpenAPI description from a CSDL document + * @param {object} csdl CSDL document + * @param {object} options Optional parameters + * @return {object} OpenAPI description + */ +module.exports.csdl2openapi = function ( + csdl, + { + url: serviceRoot, + servers: serversObject, + odataVersion: odataVersion, + scheme: scheme = 'https', + host: host = 'localhost', + basePath: basePath = '/service-root', + diagram: diagram = false, + maxLevels: maxLevels = 5 + } = {} +) { + // as preProcess below mutates the csdl, copy it before, to avoid side-effects on the caller side + csdl = JSON.parse(JSON.stringify(csdl)) + csdl.$Version = odataVersion ? odataVersion : '4.01' + serviceRoot = serviceRoot || (scheme + '://' + host + basePath); + const queryOptionPrefix = csdl.$Version <= '4.01' ? '$' : ''; + const typesToInline = {}; // filled in schema() and used in inlineTypes() + const boundOverloads = {}; + const derivedTypes = {}; + const alias = {}; + const namespace = { 'Edm': 'Edm' }; + const namespaceUrl = {}; + const voc = {}; + const requiredSchemas = { list: [], used: {} }; + + preProcess(csdl, boundOverloads, derivedTypes, alias, namespace, namespaceUrl, voc); + + const entityContainer = csdl.$EntityContainer ? modelElement(csdl.$EntityContainer) : {}; + if (csdl.$EntityContainer) { + let serviceName = nameParts(csdl.$EntityContainer).qualifier; + Object.keys(entityContainer).forEach(element => { + if (entityContainer[element].$Type) { + let type = nameParts(entityContainer[element].$Type).name; + if ((csdl[serviceName]?.[type]?.['@cds.autoexpose'] || csdl[serviceName]?.[type]?.['@cds.autoexposed']) && !entityContainer[type]) + entityContainer[element]['$cds.autoexpose'] = true; + } + }); + } + + const keyAsSegment = entityContainer ? entityContainer[voc.Capabilities.KeyAsSegmentSupported] : {}; + + const openapi = { + openapi: '3.0.2', + info: getInfo(csdl, entityContainer), + 'x-sap-api-type': 'ODATAV4', + 'x-odata-version': csdl.$Version, + 'x-sap-shortText': getShortText(csdl, entityContainer), + servers: getServers(serviceRoot, serversObject), + tags: entityContainer ? getTags(entityContainer) : {}, + paths: entityContainer ? getPaths(entityContainer) : {}, + components: getComponents(csdl, entityContainer) + }; + + const externalDocs = getExternalDoc(csdl); + if (externalDocs && Object.keys(externalDocs).length > 0) { + openapi.externalDocs = externalDocs; + } + const extensions = getExtensions(csdl, 'root'); + if (extensions && Object.keys(extensions).length > 0) { + Object.assign(openapi, extensions); + } + + // function to read @OpenAPI.Extensions and get them in the generated openAPI document + function getExtensions(csdl, level) { + let extensionObj = {}; + let containerSchema = {}; + if (level ==='root'){ + const namespace = csdl.$EntityContainer ? nameParts(csdl.$EntityContainer).qualifier : null; + containerSchema = csdl.$EntityContainer ? csdl[namespace] : {}; + } + else if(level === 'schema' || level === 'operation'){ + containerSchema = csdl; + } + + for (const [key, value] of Object.entries(containerSchema)) { + if (key.startsWith('@OpenAPI.Extensions')) { + const annotationProperties = key.split('@OpenAPI.Extensions.')[1]; + const keys = annotationProperties.split('.'); + if (!keys[0].startsWith("x-sap-")) { + keys[0] = (keys[0].startsWith("sap-") ? "x-" : "x-sap-") + keys[0]; + } + if (keys.length === 1) { + extensionObj[keys[0]] = value; + } else { + nestedAnnotation(extensionObj, keys[0], keys, value); + } + } + } + let extensionEnums = { + "x-sap-compliance-level": {allowedValues: ["sap:base:v1", "sap:core:v1", "sap:core:v2" ] } , + "x-sap-api-type": {allowedValues: [ "ODATA", "ODATAV4", "REST" , "SOAP"] }, + "x-sap-direction": {allowedValues: ["inbound", "outbound", "mixed"] , default : "inbound" }, + "x-sap-dpp-entity-semantics": {allowedValues: ["sap:DataSubject", "sap:DataSubjectDetails", "sap:Other"] }, + "x-sap-dpp-field-semantics": {allowedValues: ["sap:DataSubjectID", "sap:ConsentID", "sap:PurposeID", "sap:ContractRelatedID", "sap:LegalEntityID", "sap:DataControllerID", "sap:UserID", "sap:EndOfBusinessDate", "sap:BlockingDate", "sap:EndOfRetentionDate"] }, + }; + checkForExtentionEnums(extensionObj, extensionEnums); + + let extenstionSchema = { + "x-sap-stateInfo": ['state', 'deprecationDate', 'decomissionedDate', 'link'], + "x-sap-ext-overview": ['name', 'values'], + "x-sap-deprecated-operation" : ['deprecationDate', 'successorOperationRef', "successorOperationId"], + "x-sap-odm-semantic-key" : ['name', 'values'], + }; + + checkForExtentionSchema(extensionObj, extenstionSchema); + return extensionObj; + } + + function checkForExtentionEnums(extensionObj, extensionEnums){ + for (const [key, value] of Object.entries(extensionObj)) { + if(extensionEnums[key] && extensionEnums[key].allowedValues && !extensionEnums[key].allowedValues.includes(value)){ + if(extensionEnums[key].default){ + extensionObj[key] = extensionEnums[key].default; + } + else{ + delete extensionObj[key]; + } + } + } + } + + function checkForExtentionSchema(extensionObj, extenstionSchema) { + for (const [key, value] of Object.entries(extensionObj)) { + if (extenstionSchema[key]) { + if (Array.isArray(value)) { + extensionObj[key] = value.filter((v) => extenstionSchema[key].includes(v)); + } else if (typeof value === "object" && value !== null) { + for (const field in value) { + if (!extenstionSchema[key].includes(field)) { + delete extensionObj[key][field]; + } + } + } + } + } + } + + + function nestedAnnotation(resObj, openapiProperty, keys, value) { + if (resObj[openapiProperty] === undefined) { + resObj[openapiProperty] = {}; + } + + let node = resObj[openapiProperty]; + + // traverse the annotation property and define the objects if they're not defined + for (let nestedIndex = 1; nestedIndex < keys.length - 1; nestedIndex++) { + const nestedElement = keys[nestedIndex]; + if (node[nestedElement] === undefined) { + node[nestedElement] = {}; + } + node = node[nestedElement]; + } + + // set value annotation property + node[keys[keys.length - 1]] = value; + } + + if (!csdl.$EntityContainer) { + delete openapi.servers; + delete openapi.tags; + } + + security(openapi, entityContainer); + + return openapi; + + + /** + * Collect model info for easier lookup + * @param {object} csdl CSDL document + * @param {object} boundOverloads Map of action/function names to bound overloads + * @param {object} derivedTypes Map of type names to derived types + * @param {object} alias Map of namespace or alias to alias + * @param {object} namespace Map of namespace or alias to namespace + * @param {object} namespaceUrl Map of namespace to reference URL + * @param {object} voc Map of vocabularies and terms + */ + function preProcess(csdl, boundOverloads, derivedTypes, alias, namespace, namespaceUrl, voc) { + Object.keys(csdl.$Reference || {}).forEach(url => { + const reference = csdl.$Reference[url]; + (reference.$Include || []).forEach(include => { + const qualifier = include.$Alias || include.$Namespace; + alias[include.$Namespace] = qualifier; + namespace[qualifier] = include.$Namespace; + namespace[include.$Namespace] = include.$Namespace; + namespaceUrl[include.$Namespace] = url; + }); + }); + + getVocabularies(voc, alias); + + Object.keys(csdl).filter(name => isIdentifier(name)).forEach(name => { + const schema = csdl[name]; + const qualifier = schema.$Alias || name; + const isDefaultNamespace = schema[voc.Core.DefaultNamespace]; + + alias[name] = qualifier; + namespace[qualifier] = name; + namespace[name] = name; + + Object.keys(schema).filter(iName => isIdentifier(iName)).forEach(iName2 => { + const qualifiedName = qualifier + '.' + iName2; + const element = schema[iName2]; + if (Array.isArray(element)) { + element.filter(overload => overload.$IsBound).forEach(overload => { + const type = overload.$Parameter[0].$Type + (overload.$Parameter[0].$Collection ? '-c' : ''); + if (!boundOverloads[type]) boundOverloads[type] = []; + boundOverloads[type].push({ name: (isDefaultNamespace ? iName2 : qualifiedName), overload: overload }); + }); + } else if (element.$BaseType) { + const base = namespaceQualifiedName(element.$BaseType, namespace); + if (!derivedTypes[base]) derivedTypes[base] = []; + derivedTypes[base].push(qualifiedName); + } + }); + + Object.keys(schema.$Annotations || {}).forEach(target => { + const annotations = schema.$Annotations[target]; + const segments = target.split('/'); + const open = segments[0].indexOf('('); + let element; + if (open == -1) { + element = modelElement(segments[0]); + } else { + element = modelElement(segments[0].substring(0, open)); + let args = segments[0].substring(open + 1, segments[0].length - 1); + element = element.find( + (overload) => + (overload.$Kind == "Action" && + overload.$IsBound != true && + args == "") || + (overload.$Kind == "Action" && + args == + (overload.$Parameter[0].$Collection + ? `Collection(${overload.$Parameter[0].$Type})` + : overload.$Parameter[0].$Type || "")) || + (overload.$Parameter || []) + .map((p) => { + const type = p.$Type || "Edm.String"; + return p.$Collection ? `Collection(${type})` : type; + }) + .join(",") == args + ); + } + if (!element) { + DEBUG?.(`Invalid annotation target '${target}'`); + } else if (Array.isArray(element)) { + //TODO: action or function: + //- loop over all overloads + //- if there are more segments, a parameter or the return type is targeted + } else { + switch (segments.length) { + case 1: + Object.assign(element, annotations); + break; + case 2: + if (['Action', 'Function'].includes(element.$Kind)) { + if (segments[1] == '$ReturnType') { + if (element.$ReturnType) + Object.assign(element.$ReturnType, annotations); + } else { + const parameter = element.$Parameter.find(p => p.$Name == segments[1]); + Object.assign(parameter, annotations); + } + } else { + if (element[segments[1]]) { + Object.assign(element[segments[1]], annotations); + } else { + // DEBUG?.(`Invalid annotation target '${target}'`) + } + } + break; + default: + DEBUG?.('More than two annotation target path segments'); + } + } + }); + }); + } + + /** + * Construct map of qualified term names + * @param {object} voc Map of vocabularies and terms + * @param {object} alias Map of namespace or alias to alias + */ + function getVocabularies(voc, alias) { + const terms = { + Authorization: ['Authorizations', 'SecuritySchemes'], + Capabilities: ['BatchSupport', 'BatchSupported', 'ChangeTracking', 'CountRestrictions', 'DeleteRestrictions', 'DeepUpdateSupport', 'ExpandRestrictions', + 'FilterRestrictions', 'IndexableByKey', 'InsertRestrictions', 'KeyAsSegmentSupported', 'NavigationRestrictions', 'OperationRestrictions', + 'ReadRestrictions', 'SearchRestrictions', 'SelectSupport', 'SkipSupported', 'SortRestrictions', 'TopSupported', 'UpdateRestrictions'], + Core: ['AcceptableMediaTypes', 'Computed', 'ComputedDefaultValue', 'DefaultNamespace', 'Description', 'Example', 'Immutable', 'LongDescription', + 'OptionalParameter', 'Permissions', 'SchemaVersion'], + JSON: ['Schema'], + Validation: ['AllowedValues', 'Exclusive', 'Maximum', 'Minimum', 'Pattern'] + }; + + Object.keys(terms).forEach(vocab => { + voc[vocab] = {}; + terms[vocab].forEach(term => { + if (alias['Org.OData.' + vocab + '.V1'] != undefined) + voc[vocab][term] = '@' + alias['Org.OData.' + vocab + '.V1'] + '.' + term; + }); + }); + + voc.Common = { + Label: `@${alias['com.sap.vocabularies.Common.v1']}.Label` + } + } + + /** + * Construct the Info Object + * @param {object} csdl CSDL document + * @param {object} entityContainer Entity Container object + * @return {object} Info Object + */ + function getInfo(csdl, entityContainer) { + const namespace = csdl.$EntityContainer ? nameParts(csdl.$EntityContainer).qualifier : null; + const containerSchema = csdl.$EntityContainer ? csdl[namespace] : {}; + let description; + if (entityContainer && entityContainer[voc.Core.LongDescription]) { + description = entityContainer[voc.Core.LongDescription]; + } + else if (containerSchema && containerSchema[voc.Core.LongDescription]) { + description = containerSchema[voc.Core.LongDescription]; + } + else { + description = "Use @Core.LongDescription: '...' on your CDS service to provide a meaningful description."; + } + description += (diagram ? getResourceDiagram(csdl, entityContainer) : ''); + let title; + if (entityContainer && entityContainer[voc.Common.Label]) { + title = entityContainer[voc.Common.Label]; + } + else { + title = "Use @title: '...' on your CDS service to provide a meaningful title."; + } + return { + title: title, + description: csdl.$EntityContainer ? description : '', + version: containerSchema[voc.Core.SchemaVersion] || '' + }; + } + + /** + * Construct the externalDocs Object + * @param {object} csdl CSDL document + * @return {object} externalDocs Object + */ + function getExternalDoc(csdl) { + const namespace = csdl.$EntityContainer ? nameParts(csdl.$EntityContainer).qualifier : null; + const containerSchema = csdl.$EntityContainer ? csdl[namespace] : {}; + let externalDocs = {}; + if (containerSchema?.['@OpenAPI.externalDocs.description']) { + externalDocs.description = containerSchema['@OpenAPI.externalDocs.description']; + } + if (containerSchema?.['@OpenAPI.externalDocs.url']) { + externalDocs.url = containerSchema['@OpenAPI.externalDocs.url']; + } + return externalDocs; + } + + /** + * Construct resource diagram using web service at https://yuml.me + * @param {object} csdl CSDL document + * @param {object} entityContainer Entity Container object + * @return {string} resource diagram + */ + function getResourceDiagram(csdl, entityContainer) { + let diagram = ''; + let comma = ''; + //TODO: make colors configurable + let color = { resource: '{bg:lawngreen}', entityType: '{bg:lightslategray}', complexType: '', external: '{bg:whitesmoke}' } + + Object.keys(csdl).filter(name => isIdentifier(name)).forEach(namespace => { + const schema = csdl[namespace]; + Object.keys(schema).filter(name => isIdentifier(name) && ['EntityType', 'ComplexType'].includes(schema[name].$Kind)) + .forEach(typeName => { + const type = schema[typeName]; + diagram += comma + + (type.$BaseType ? '[' + nameParts(type.$BaseType).name + ']^' : '') + + '[' + typeName + (type.$Kind == 'EntityType' ? color.entityType : color.complexType) + ']'; + Object.keys(type).filter(name => isIdentifier(name)).forEach(propertyName => { + const property = type[propertyName]; + const targetNP = nameParts(property.$Type || 'Edm.String'); + if (property.$Kind == 'NavigationProperty' || targetNP.qualifier != 'Edm') { + const target = modelElement(property.$Type); + const bidirectional = property.$Partner && target && target[property.$Partner] && target[property.$Partner].$Partner == propertyName; + // Note: if the partner has the same name then it will also be depicted + if (!bidirectional || propertyName <= property.$Partner) { + diagram += ',[' + typeName + ']' + + ((property.$Kind != 'NavigationProperty' || property.$ContainsTarget) ? '++' : (bidirectional ? cardinality(target[property.$Partner]) : '')) + + '-' + + cardinality(property) + + ((property.$Kind != 'NavigationProperty' || bidirectional) ? '' : '>') + + '[' + + (target ? targetNP.name : property.$Type + color.external) + + ']'; + } + } + }); + comma = ','; + }); + }); + + Object.keys(entityContainer).filter(name => isIdentifier(name)).reverse().forEach(name => { + const resource = entityContainer[name]; + if (resource.$Type) { + diagram += comma + + '[' + name + '%20' + color.resource + ']' // additional space in case entity set and type have same name + + '++-' + + cardinality(resource) + + '>[' + nameParts(resource.$Type).name + ']'; + } else { + if (resource.$Action) { + diagram += comma + + '[' + name + color.resource + ']'; + const overload = modelElement(resource.$Action).find(pOverload => !pOverload.$IsBound); + diagram += overloadDiagram(name, overload); + } else if (resource.$Function) { + diagram += comma + + '[' + name + color.resource + ']'; + const overloads = modelElement(resource.$Function); + if (overloads) { + const unbound = overloads.filter(overload => !overload.$IsBound); + // TODO: loop over all overloads, add new source box after first arrow + diagram += overloadDiagram(name, unbound[0]); + } + } + } + }); + + if (diagram != '') { + diagram = '\n\n## Entity Data Model\n![ER Diagram](https://yuml.me/diagram/class/' + + diagram + + ')\n\n### Legend\n![Legend](https://yuml.me/diagram/plain;dir:TB;scale:60/class/[External.Type' + color.external + + '],[ComplexType' + color.complexType + '],[EntityType' + color.entityType + + '],[EntitySet/Singleton/Operation' + color.resource + '])'; + } + + return diagram; + + /** + * Diagram representation of property cardinality + * @param {object} typedElement Typed model element, e.g. property + * @return {string} cardinality + */ + function cardinality(typedElement) { + return typedElement.$Collection ? '*' : (typedElement.$Nullable ? '0..1' : ''); + } + + /** + * Diagram representation of action or function overload + * @param {string} name Name of action or function import + * @param {object} overload Action or function overload + * @return {string} diagram part + */ + function overloadDiagram(name, overload) { + let diag = ""; + if (overload.$ReturnType) { + const type = modelElement(overload.$ReturnType.$Type || "Edm.String"); + if (type) { + diag += "-" + cardinality(overload.$ReturnType) + ">[" + nameParts(overload.$ReturnType.$Type).name + "]"; + } + } + for (const param of overload.$Parameter || []) { + const type = modelElement(param.$Type || "Edm.String"); + if (type) { + diag += comma + "[" + name + color.resource + "]in-" + cardinality(param.$Type) + ">[" + nameParts(param.$Type).name + "]"; + } + } + return diag; + } + } + + /** + * Find model element by qualified name + * @param {string} qname Qualified name of model element + * @return {object} Model element + */ + function modelElement(qname) { + const q = nameParts(qname); + const schema = csdl[q.qualifier] || csdl[namespace[q.qualifier]]; + return schema ? schema[q.name] : null; + } + + /** + * Construct the short text + * @param {object} csdl CSDL document + * @param {object} entityContainer Entity Container object + * @return {string} short text + */ + function getShortText(csdl, entityContainer) { + const namespace = csdl.$EntityContainer ? nameParts(csdl.$EntityContainer).qualifier : null; + const containerSchema = csdl.$EntityContainer ? csdl[namespace] : {}; + let shortText; + if (entityContainer && entityContainer[voc.Core.Description]) { + shortText = entityContainer[voc.Core.Description]; + } + else if (containerSchema && containerSchema[voc.Core.Description]) { + shortText = containerSchema[voc.Core.Description]; + } + else { + shortText = "Use @Core.Description: '...' on your CDS service to provide a meaningful short text."; + } + return shortText; + } + + /** + * Construct an array of Server Objects + * @param {object} serviceRoot The service root + * @param {object} serversObject Input servers object + * @return {Array} The list of servers + */ + function getServers(serviceRoot, serversObject) { + let servers; + if (serversObject) { + try { + servers = JSON.parse(serversObject); + } catch (err) { + throw new Error(`The input server object is invalid.`); + } + + if (!servers.length) { + throw new Error(`The input server object should be an array.`); + } + } else { + servers = [{ url: serviceRoot }]; + } + return servers; + } + + /** + * Construct an array of Tag Objects from the entity container + * @param {object} container The entity container + * @return {Array} The list of tags + */ + function getTags(container) { + const tags = new Map(); + // all entity sets and singletons + Object.keys(container) + .filter(name => isIdentifier(name) && container[name].$Type) + .forEach(child => { + const type = modelElement(container[child].$Type) || {}; + const tag = { + name: type[voc.Common.Label] || child + }; + const description = container[child][voc.Core.Description] || type[voc.Core.Description]; + if (description) tag.description = description; + tags.set(tag.name, tag); + }); + return Array.from(tags.values()).sort((pre, next) => pre.name.localeCompare(next.name)); + } + + /** + * Construct the Paths Object from the entity container + * @param {object} container Entity container + * @return {object} Paths Object + */ + function getPaths(container) { + const paths = {}; + const resources = Object.keys(container).filter(name => isIdentifier(name)); + resources.forEach(name => { + let child = container[name]; + if (child.$Type) { + const type = modelElement(child.$Type); + const sourceName = (type && type[voc.Common.Label]) || name; + // entity sets and singletons are almost containment navigation properties + child.$ContainsTarget = true; + pathItems(paths, '/' + name, [], child, child, sourceName, sourceName, child, 0, ''); + } else if (child.$Action) { + pathItemActionImport(paths, name, child); + } else if (child.$Function) { + pathItemFunctionImport(paths, name, child); + } else { + DEBUG?.('Unrecognized entity container child: ' + name); + } + }) + if (resources.length > 0) pathItemBatch(paths, container); + return Object.keys(paths).sort().reduce((p, c) => (p[c] = paths[c], p), {}); + } + + /** + * Add path and Path Item Object for a navigation segment + * @param {object} paths Paths Object to augment + * @param {string} prefix Prefix for path + * @param {Array} prefixParameters Parameter Objects for prefix + * @param {object} element Model element of navigation segment + * @param {object} root Root model element + * @param {string} sourceName Name of path source + * @param {string} targetName Name of path target + * @param {string} target Target container child of path + * @param {integer} level Number of navigation segments so far + * @param {string} navigationPath Path for finding navigation restrictions + */ + function pathItems(paths, prefix, prefixParameters, element, root, sourceName, targetName, target, level, navigationPath) { + const name = prefix.substring(prefix.lastIndexOf('/') + 1); + const type = modelElement(element.$Type); + const pathItem = {}; + const restrictions = navigationPropertyRestrictions(root, navigationPath); + const nonExpandable = nonExpandableProperties(root, navigationPath); + + paths[prefix] = pathItem; + if (prefixParameters.length > 0) pathItem.parameters = prefixParameters; + + operationRead(pathItem, element, name, sourceName, targetName, target, level, restrictions, false, nonExpandable); + if (!root['$cds.autoexpose'] && element.$Collection && (element.$ContainsTarget || level < 2 && target)) { + operationCreate(pathItem, element, name, sourceName, targetName, target, level, restrictions); + } + pathItemsForBoundOperations(paths, prefix, prefixParameters, element, sourceName); + + if (element.$ContainsTarget) { + if (element.$Collection) { + if (level < maxLevels) + pathItemsWithKey(paths, prefix, prefixParameters, element, root, sourceName, targetName, target, level, navigationPath, restrictions, nonExpandable); + } else { + if (!root['$cds.autoexpose']) { + operationUpdate(pathItem, element, name, sourceName, target, level, restrictions); + if (element.$Nullable) { + operationDelete(pathItem, element, name, sourceName, target, level, restrictions); + } + } + pathItemsForBoundOperations(paths, prefix, prefixParameters, element, sourceName); + pathItemsWithNavigation(paths, prefix, prefixParameters, type, root, sourceName, level, navigationPath); + } + } + + if (Object.keys(pathItem).filter((i) => i !== "parameters").length === 0) + delete paths[prefix]; + } + + /** + * Find navigation restrictions for a navigation path + * @param {object} root Root model element + * @param {string} navigationPath Path for finding navigation restrictions + * @return Navigation property restrictions of navigation segment + */ + function navigationPropertyRestrictions(root, navigationPath) { + const navigationRestrictions = root[voc.Capabilities.NavigationRestrictions] || {}; + return (navigationRestrictions.RestrictedProperties || []).find(item => navigationPropertyPath(item.NavigationProperty) == navigationPath) + || {}; + } + + /** + * Find non-expandable properties for a navigation path + * @param {object} root Root model element + * @param {string} navigationPath Path for finding navigation restrictions + * @return Navigation property restrictions of navigation segment + */ + function nonExpandableProperties(root, navigationPath) { + const expandRestrictions = root[voc.Capabilities.ExpandRestrictions] || {}; + const prefix = navigationPath.length === 0 ? '' : navigationPath + '/' + const from = prefix.length + const nonExpandable = [] + for (const path of (expandRestrictions.NonExpandableProperties || [])) { + if (path.startsWith(prefix)) { + nonExpandable.push(path.substring(from)) + } + } + return nonExpandable; + } + + /** + * Add path and Path Item Object for a navigation segment with key + * @param {object} paths Paths Object to augment + * @param {string} prefix Prefix for path + * @param {Array} prefixParameters Parameter Objects for prefix + * @param {object} element Model element of navigation segment + * @param {object} root Root model element + * @param {string} sourceName Name of path source + * @param {string} targetName Name of path target + * @param {string} target Target container child of path + * @param {integer} level Number of navigation segments so far + * @param {string} navigationPath Path for finding navigation restrictions + * @param {object} restrictions Navigation property restrictions of navigation segment + * @param {array} nonExpandable Non-expandable navigation properties + */ + function pathItemsWithKey(paths, prefix, prefixParameters, element, root, sourceName, targetName, target, level, navigationPath, restrictions, nonExpandable) { + const targetIndexable = target == null || target[voc.Capabilities.IndexableByKey] != false; + if (restrictions.IndexableByKey == true || restrictions.IndexableByKey != false && targetIndexable) { + const name = prefix.substring(prefix.lastIndexOf('/') + 1); + const type = modelElement(element.$Type); + const key = entityKey(type, level); + if (key.parameters.length > 0) { + const path = prefix + key.segment; + const parameters = prefixParameters.concat(key.parameters); + const pathItem = { parameters: parameters }; + paths[path] = pathItem; + + operationRead(pathItem, element, name, sourceName, targetName, target, level, restrictions, true, nonExpandable); + if (!root['$cds.autoexpose']) { + operationUpdate(pathItem, element, name, sourceName, target, level, restrictions, true); + operationDelete(pathItem, element, name, sourceName, target, level, restrictions, true); + } + if (Object.keys(pathItem).filter((i) => i !== "parameters").length === 0) + delete paths[path]; + + pathItemsForBoundOperations(paths, path, parameters, element, sourceName, true); + pathItemsWithNavigation(paths, path, parameters, type, root, sourceName, level, navigationPath); + } + } + } + + /** + * Construct Operation Object for create + * @param {object} pathItem Path Item Object to augment + * @param {object} element Model element of navigation segment + * @param {string} name Name of navigation segment + * @param {string} sourceName Name of path source + * @param {string} targetName Name of path target + * @param {string} target Target container child of path + * @param {integer} level Number of navigation segments so far + * @param {object} restrictions Navigation property restrictions of navigation segment + */ + function operationCreate(pathItem, element, name, sourceName, targetName, target, level, restrictions) { + const insertRestrictions = restrictions.InsertRestrictions || target && target[voc.Capabilities.InsertRestrictions] || {}; + let countRestrictions = target && (target[voc.Capabilities.CountRestrictions]?.Countable === false); // count property will be added if CountRestrictions is false + if (insertRestrictions.Insertable !== false) { + const lname = pluralize.singular(splitName(name)); + const type = modelElement(element.$Type); + pathItem.post = { + summary: insertRestrictions.Description || operationSummary('Creates', name, sourceName, level, true, true), + tags: [sourceName], + requestBody: { + description: type && type[voc.Core.Description] || 'New ' + lname, + required: true, + content: { + 'application/json': { + schema: ref(element.$Type, SUFFIX.create), + } + } + }, + responses: response(201, 'Created ' + lname, { $Type: element.$Type }, insertRestrictions.ErrorResponses, !countRestrictions), + }; + if (insertRestrictions.LongDescription) pathItem.post.description = insertRestrictions.LongDescription; + if (targetName && sourceName != targetName) pathItem.post.tags.push(targetName); + customParameters(pathItem.post, insertRestrictions); + } + } + + /** + * Split camel-cased name into words + * @param {string} name Name to split + * @return {string} Split name + */ + function splitName(name) { + return name.split(/(?=[A-Z])/g).join(' ').toLowerCase().replace(/ i d/g, ' id'); + } + + /** + * Construct operation summary + * @param {string} operation Operation (verb) + * @param {string} name Name of navigation segment + * @param {string} sourceName Name of path source + * @param {integer} level Number of navigation segments so far + * @param {boolean} collection Access a collection + * @param {boolean} byKey Access by key + * @return {string} Operation Text + */ + function operationSummary(operation, name, sourceName, level, collection, byKey) { + let lname = splitName(name); + let sname = splitName(sourceName); + + return operation + ' ' + + (byKey ? 'a single ' : (collection ? 'a list of ' : '')) + + (byKey ? pluralize.singular(lname) : lname) + //TODO: suppress "a" for all singletons + + (level == 0 ? '' : (level == 1 && sname == 'me' ? ' of me' : ' of a ' + pluralize.singular(sname))) + + '.' + } + + /** + * Construct Operation Object for read + * @param {object} pathItem Path Item Object to augment + * @param {object} element Model element of navigation segment + * @param {string} name Name of navigation segment + * @param {string} sourceName Name of path source + * @param {string} targetName Name of path target + * @param {string} target Target container child of path + * @param {integer} level Number of navigation segments so far + * @param {object} restrictions Navigation property restrictions of navigation segment + * @param {boolean} byKey Read by key + * @param {array} nonExpandable Non-expandable navigation properties + */ + function operationRead(pathItem, element, name, sourceName, targetName, target, level, restrictions, byKey, nonExpandable) { + const targetRestrictions = target?.[voc.Capabilities.ReadRestrictions]; + const readRestrictions = restrictions.ReadRestrictions || targetRestrictions || {}; + const readByKeyRestrictions = readRestrictions.ReadByKeyRestrictions; + let readable = true; + let countRestrictions = target && (target[voc.Capabilities.CountRestrictions]?.Countable === false); + if (byKey && readByKeyRestrictions && readByKeyRestrictions.Readable !== undefined) + readable = readByKeyRestrictions.Readable; + else if (readRestrictions.Readable !== undefined) + readable = readRestrictions.Readable; + + if (readable) { + let descriptions = (level == 0 ? targetRestrictions : restrictions.ReadRestrictions) || {}; + if (byKey) descriptions = descriptions.ReadByKeyRestrictions || {}; + const lname = splitName(name); + const collection = !byKey && element.$Collection; + const operation = { + summary: descriptions.Description || operationSummary('Retrieves', name, sourceName, level, element.$Collection, byKey), + tags: [sourceName], + parameters: [], + responses: response(200, 'Retrieved ' + (byKey ? pluralize.singular(lname) : lname), { $Type: element.$Type, $Collection: collection }, + byKey ? readByKeyRestrictions?.ErrorResponses : readRestrictions?.ErrorResponses, !countRestrictions) + }; + const deltaSupported = element[voc.Capabilities.ChangeTracking] && element[voc.Capabilities.ChangeTracking].Supported; + if (!byKey && deltaSupported) { + operation.responses[200].content['application/json'].schema.properties['@odata.deltaLink'] = { + type: 'string', + example: basePath + '/' + name + '?$deltatoken=opaque server-generated token for fetching the delta' + } + } + if (descriptions.LongDescription) operation.description = descriptions.LongDescription; + if (target && sourceName != targetName) operation.tags.push(targetName); + customParameters(operation, byKey ? readByKeyRestrictions || readRestrictions : readRestrictions); + + if (collection) { + optionTop(operation.parameters, target, restrictions); + optionSkip(operation.parameters, target, restrictions); + if (csdl.$Version >= '4.0') optionSearch(operation.parameters, target, restrictions); + optionFilter(operation.parameters, target, restrictions); + optionCount(operation.parameters, target); + optionOrderBy(operation.parameters, element, target, restrictions); + } + + optionSelect(operation.parameters, element, target, restrictions); + optionExpand(operation.parameters, element, target, nonExpandable); + + pathItem.get = operation; + } + } + + /** + * Add custom headers and query options + * @param {object} operation Operation object to augment + * @param {object} restrictions Restrictions for operation + */ + function customParameters(operation, restrictions) { + if ( + !operation.parameters && + (restrictions.CustomHeaders || restrictions.CustomQueryOptions) + ) + operation.parameters = []; + for (const custom of restrictions.CustomHeaders || []) { + operation.parameters.push(customParameter(custom, "header")); + } + + for (const custom of restrictions.CustomQueryOptions || []) { + operation.parameters.push(customParameter(custom, "query")); + } + } + + /** + * Construct custom parameter + * @param {object} custom custom parameter in OData format + * @param {string} location "header" or "query" + */ + function customParameter(custom, location) { + return { + name: custom.Name, + in: location, + required: custom.Required || false, + ...(custom.Description && { description: custom.Description }), + schema: { + type: "string", + ...(custom.DocumentationURL && { + externalDocs: { url: custom.DocumentationURL }, + }), + //TODO: Examples + }, + }; + } + + /** + * Add parameter for query option $count + * @param {Array} parameters Array of parameters to augment + * @param {string} target Target container child of path + */ + function optionCount(parameters, target) { + const targetRestrictions = target && target[voc.Capabilities.CountRestrictions]; + const targetCountable = target == null + || targetRestrictions == null + || targetRestrictions.Countable !== false; + + if (targetCountable) { + parameters.push({ + + $ref: '#/components/parameters/count' + }); + } + } + + /** + * Add parameter for query option $expand + * @param {Array} parameters Array of parameters to augment + * @param {object} element Model element of navigation segment + * @param {string} target Target container child of path + * @param {array} nonExpandable Non-expandable navigation properties + */ + function optionExpand(parameters, element, target, nonExpandable) { + const targetRestrictions = target && target[voc.Capabilities.ExpandRestrictions]; + const supported = targetRestrictions == null || targetRestrictions.Expandable != false; + if (supported) { + const expandItems = ['*'].concat(navigationPaths(element).filter(path => !nonExpandable.includes(path))); + if (expandItems.length > 1) { + parameters.push({ + name: queryOptionPrefix + 'expand', + description: (targetRestrictions && targetRestrictions[voc.Core.Description]) + || 'The value of $expand query option is a comma-separated list of navigation property names, \ +stream property names, or $value indicating the stream content of a media-entity. \ +The corresponding related entities and stream values will be represented inline, \ +see [Expand](http://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part1-protocol.html#sec_SystemQueryOptionexpand)', + in: 'query', + explode: false, + schema: { + type: 'array', + uniqueItems: true, + items: { + type: 'string', + enum: expandItems + } + } + }); + } + } + } + + /** + * Collect navigation paths of a navigation segment and its potentially structured components + * @param {object} element Model element of navigation segment + * @param {string} prefix Navigation prefix + * @param {integer} level Number of navigation segments so far + * @return {Array} Array of navigation property paths + */ + function navigationPaths(element, prefix = '', level = 0) { + const paths = []; + const type = modelElement(element.$Type); + const properties = propertiesOfStructuredType(type); + Object.keys(properties).forEach(key => { + if (properties[key].$Kind == 'NavigationProperty') { + paths.push(prefix + key) + } else if (properties[key].$Type && level < maxLevels) { + paths.push(...navigationPaths(properties[key], prefix + key + '/', level + 1)); + } + }) + return paths; + } + + /** + * Add parameter for query option $filter + * @param {Array} parameters Array of parameters to augment + * @param {string} target Target container child of path + * @param {object} restrictions Navigation property restrictions of navigation segment + */ + function optionFilter(parameters, target, restrictions) { + const filterRestrictions = restrictions.FilterRestrictions || target && target[voc.Capabilities.FilterRestrictions] || {}; + + if (filterRestrictions.Filterable !== false) { + const filter = { + name: queryOptionPrefix + 'filter', + description: filterRestrictions[voc.Core.Description] + || 'Filter items by property values, see [Filtering](http://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part1-protocol.html#sec_SystemQueryOptionfilter)', + in: 'query', + schema: { + type: 'string' + } + }; + if (filterRestrictions.RequiresFilter) + filter.required = true; + if (filterRestrictions.RequiredProperties) { + filter.description += '\n\nRequired filter properties:'; + filterRestrictions.RequiredProperties.forEach( + item => filter.description += '\n- ' + propertyPath(item) + ); + } + parameters.push(filter); + } + } + + /** + * Add parameter for query option $orderby + * @param {Array} parameters Array of parameters to augment + * @param {object} element Model element of navigation segment + * @param {string} target Target container child of path + * @param {object} restrictions Navigation property restrictions of navigation segment + */ + function optionOrderBy(parameters, element, target, restrictions) { + const sortRestrictions = restrictions.SortRestrictions || target && target[voc.Capabilities.SortRestrictions] || {}; + + if (sortRestrictions.Sortable !== false) { + const nonSortable = {}; + (sortRestrictions.NonSortableProperties || []).forEach(name => { + nonSortable[propertyPath(name)] = true; + }); + const orderbyItems = []; + primitivePaths(element).filter(property => !nonSortable[property]).forEach(property => { + orderbyItems.push(property); + orderbyItems.push(property + ' desc'); + }); + if (orderbyItems.length > 0) { + parameters.push({ + name: queryOptionPrefix + 'orderby', + description: sortRestrictions[voc.Core.Description] + || 'Order items by property values, see [Sorting](http://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part1-protocol.html#sec_SystemQueryOptionorderby)', + in: 'query', + explode: false, + schema: { + type: 'array', + uniqueItems: true, + items: { + type: 'string', + enum: orderbyItems + } + } + }); + } + } + } + + /** + * Unpack EnumMember value if it uses CSDL JSON CS01 style, like CAP does + * @param {string or object} path Qualified name of referenced type + * @return {object} Reference Object + */ + function enumMember(member) { + if (typeof member == 'string') + return member; + else if (typeof member == 'object') + return member.$EnumMember; + } + + /** + * Unpack NavigationPropertyPath value if it uses CSDL JSON CS01 style, like CAP does + * @param {string or object} path Qualified name of referenced type + * @return {object} Reference Object + */ + function navigationPropertyPath(path) { + if (typeof path == 'string') + return path; + else + return path.$NavigationPropertyPath; + } + + /** + * Unpack PropertyPath value if it uses CSDL JSON CS01 style, like CAP does + * @param {string or object} path Qualified name of referenced type + * @return {object} Reference Object + */ + function propertyPath(path) { + if (typeof path == 'string') + return path; + else + return path.$PropertyPath; + } + + /** + * Collect primitive paths of a navigation segment and its potentially structured components + * @param {object} element Model element of navigation segment + * @param {string} prefix Navigation prefix + * @return {Array} Array of primitive property paths + */ + function primitivePaths(element, prefix = '') { + const paths = []; + const elementType = modelElement(element.$Type); + + if (!elementType) { + DEBUG?.(`Unknown type for element: ${JSON.stringify(element)}`); + return paths; + } + + const propsOfType = propertiesOfStructuredType(elementType); + const ignore = Object.entries(propsOfType) + .filter(entry => entry[1].$Kind !== 'NavigationProperty') + .filter(entry => entry[1].$Type) + .filter(entry => nameParts(entry[1].$Type).qualifier !== 'Edm') + .filter(entry => !modelElement(entry[1].$Type)); + + // Keep old logging + ignore.forEach(entry => DEBUG?.(`Unknown type for element: ${JSON.stringify(entry)}`)); + + const properties = Object.entries(propsOfType) + .filter(entry => entry[1].$Kind !== 'NavigationProperty') + .filter(entry => !ignore.includes(entry)) + .map(entryToProperty({ path: prefix, typeRefChain: [] })); + + for (let i = 0; i < properties.length; i++) { + const property = properties[i]; + if (!property.isComplex) { + paths.push(property.path); + continue; + } + + const typeRefChainTail = property.typeRefChain[property.typeRefChain.length - 1]; + + // Allow full cycle to be shown (0) times + if (property.typeRefChain.filter(_type => _type === typeRefChainTail).length > 1) { + DEBUG?.(`Cycle detected ${property.typeRefChain.join('->')}`); + continue; + } + + const expanded = Object.entries(property.properties) + .filter(pProperty => pProperty[1].$Kind !== 'NavigationProperty') + .map(entryToProperty(property)) + properties.splice(i + 1, 0, ...expanded); + } + + return paths; + } + + function entryToProperty(parent) { + + return function (entry) { + const key = entry[0]; + const property = entry[1]; + const propertyType = property.$Type && modelElement(property.$Type); + + if (propertyType && propertyType.$Kind && propertyType.$Kind === 'ComplexType') { + return { + properties: propertiesOfStructuredType(propertyType), + path: `${parent.path}${key}/`, + typeRefChain: parent.typeRefChain.concat(property.$Type), + isComplex: true + } + } + + return { + properties: {}, + path: `${parent.path}${key}`, + typeRefChain: [], + isComplex: false, + } + }; + } + + /** + * Add parameter for query option $search + * @param {Array} parameters Array of parameters to augment + * @param {string} target Target container child of path + * @param {object} restrictions Navigation property restrictions of navigation segment + */ + function optionSearch(parameters, target, restrictions) { + const searchRestrictions = restrictions.SearchRestrictions || target && target[voc.Capabilities.SearchRestrictions] || {}; + + if (searchRestrictions.Searchable !== false) { + if (searchRestrictions[voc.Core.Description]) { + parameters.push({ + name: queryOptionPrefix + 'search', + description: searchRestrictions[voc.Core.Description], + in: 'query', + schema: { type: 'string' } + }); + } else { + parameters.push({ $ref: '#/components/parameters/search' }); + } + } + } + + /** + * Add parameter for query option $select + * @param {Array} parameters Array of parameters to augment + * @param {object} element Model element of navigation segment + * @param {string} target Target container child of path + * @param {object} restrictions Navigation property restrictions of navigation segment + */ + function optionSelect(parameters, element, target, restrictions) { + const selectSupport = restrictions.SelectSupport || target && target[voc.Capabilities.SelectSupport] || {}; + + if (selectSupport.Supported !== false) { + const type = modelElement(element.$Type) || {}; + const properties = propertiesOfStructuredType(type); + const selectItems = []; + Object.keys(properties).filter(key => properties[key].$Kind != 'NavigationProperty').forEach( + key => selectItems.push(key) + ) + if (selectItems.length > 0) { + parameters.push({ + name: queryOptionPrefix + 'select', + description: 'Select properties to be returned, see [Select](http://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part1-protocol.html#sec_SystemQueryOptionselect)', + in: 'query', + explode: false, + schema: { + type: 'array', + uniqueItems: true, + items: { + type: 'string', + enum: selectItems + } + } + }); + } + } + } + + /** + * Add parameter for query option $skip + * @param {Array} parameters Array of parameters to augment + * @param {string} target Target container child of path + * @param {object} restrictions Navigation property restrictions of navigation segment + */ + function optionSkip(parameters, target, restrictions) { + const supported = restrictions.SkipSupported !== undefined + ? restrictions.SkipSupported + : target == null || target[voc.Capabilities.SkipSupported] !== false; + + if (supported) { + parameters.push({ + $ref: '#/components/parameters/skip' + }); + } + } + + /** + * Add parameter for query option $top + * @param {Array} parameters Array of parameters to augment + * @param {string} target Target container child of path + * @param {object} restrictions Navigation property restrictions of navigation segment + */ + function optionTop(parameters, target, restrictions) { + const supported = restrictions.TopSupported !== undefined + ? restrictions.TopSupported + : target == null || target[voc.Capabilities.TopSupported] !== false; + + if (supported) { + parameters.push({ + $ref: '#/components/parameters/top' + }); + } + } + + /** + * Construct Operation Object for update + * @param {object} pathItem Path Item Object to augment + * @param {object} element Model element of navigation segment + * @param {string} name Name of navigation segment + * @param {string} sourceName Name of path source + * @param {string} target Target container child of path + * @param {integer} level Number of navigation segments so far + * @param {object} restrictions Navigation property restrictions of navigation segment + * @param {boolean} byKey Update by key + */ + function operationUpdate(pathItem, element, name, sourceName, target, level, restrictions, byKey) { + const updateRestrictions = restrictions.UpdateRestrictions || target && target[voc.Capabilities.UpdateRestrictions] || {}; + let countRestrictions = target && (target[voc.Capabilities.CountRestrictions]?.Countable === false); + if (updateRestrictions.Updatable !== false) { + const type = modelElement(element.$Type); + const operation = { + summary: updateRestrictions.Description || operationSummary('Changes', name, sourceName, level, element.$Collection, byKey), + tags: [sourceName], + requestBody: { + description: type && type[voc.Core.Description] || 'New property values', + required: true, + content: { + 'application/json': { + schema: ref(element.$Type, SUFFIX.update), + } + } + }, + responses: response(204, "Success", undefined, updateRestrictions.ErrorResponses, !countRestrictions), + }; + if (updateRestrictions.LongDescription) operation.description = updateRestrictions.LongDescription; + customParameters(operation, updateRestrictions); + const updateMethod = updateRestrictions.UpdateMethod ? updateRestrictions.UpdateMethod.toLowerCase() : "patch"; + pathItem[updateMethod] = operation; + } + } + + /** + * Construct Operation Object for delete + * @param {object} pathItem Path Item Object to augment + * @param {object} element Model element of navigation segment + * @param {string} name Name of navigation segment + * @param {string} sourceName Name of path source + * @param {string} target Target container child of path + * @param {integer} level Number of navigation segments so far + * @param {object} restrictions Navigation property restrictions of navigation segment + * @param {boolean} byKey Delete by key + */ + function operationDelete(pathItem, element, name, sourceName, target, level, restrictions, byKey) { + const deleteRestrictions = restrictions.DeleteRestrictions || target && target[voc.Capabilities.DeleteRestrictions] || {}; + let countRestrictions = target && (target[voc.Capabilities.CountRestrictions]?.Countable === false); + if (deleteRestrictions.Deletable !== false) { + pathItem.delete = { + summary: deleteRestrictions.Description || operationSummary('Deletes', name, sourceName, level, element.$Collection, byKey), + tags: [sourceName], + responses: response(204, "Success", undefined, deleteRestrictions.ErrorResponses, !countRestrictions), + }; + if (deleteRestrictions.LongDescription) pathItem.delete.description = deleteRestrictions.LongDescription; + customParameters(pathItem.delete, deleteRestrictions); + } + } + + /** + * Add paths and Path Item Objects for navigation segments + * @param {object} paths The Paths Object to augment + * @param {string} prefix Prefix for path + * @param {Array} prefixParameters Parameter Objects for prefix + * @param {object} type Entity type object of navigation segment + * @param {string} sourceName Name of path source + * @param {integer} level Number of navigation segments so far + * @param {string} navigationPrefix Path for finding navigation restrictions + */ + function pathItemsWithNavigation(paths, prefix, prefixParameters, type, root, sourceName, level, navigationPrefix) { + const navigationRestrictions = root[voc.Capabilities.NavigationRestrictions] || {}; + const rootNavigable = level == 0 && enumMember(navigationRestrictions.Navigability) != 'None' + || level == 1 && enumMember(navigationRestrictions.Navigability) != 'Single' + || level > 1; + + if (type && level < maxLevels) { + const properties = navigationPathMap(type); + Object.keys(properties).forEach(name => { + const parentRestrictions = navigationPropertyRestrictions(root, navigationPrefix); + if (enumMember(parentRestrictions.Navigability) == 'Single') return; + + const navigationPath = navigationPrefix + (navigationPrefix.length > 0 ? '/' : '') + name; + const restrictions = navigationPropertyRestrictions(root, navigationPath); + if (['Recursive', 'Single'].includes(enumMember(restrictions.Navigability)) + || restrictions.Navigability == null && rootNavigable) { + const targetSetName = root.$NavigationPropertyBinding && root.$NavigationPropertyBinding[navigationPath]; + const target = entityContainer[targetSetName]; + const targetType = target && modelElement(target.$Type); + const targetName = (targetType && targetType[voc.Common.Label]) || targetSetName; + pathItems(paths, prefix + '/' + name, prefixParameters, properties[name], root, sourceName, targetName, target, level + 1, navigationPath); + } + }); + } + } + + /** + * Collect navigation paths of a navigation segment and its potentially structured components + * @param {object} type Structured type + * @param {object} map Map of navigation property paths and their types + * @param {string} prefix Navigation prefix + * @param {integer} level Number of navigation segments so far + * @return {object} Map of navigation property paths and their types + */ + function navigationPathMap(type, map = {}, prefix = '', level = 0) { + const properties = propertiesOfStructuredType(type); + Object.keys(properties).forEach(key => { + if (properties[key].$Kind == 'NavigationProperty') { + map[prefix + key] = properties[key]; + } else if (properties[key].$Type && !properties[key].$Collection && level < maxLevels) { + navigationPathMap(modelElement(properties[key].$Type), map, prefix + key + '/', level + 1); + } + }) + return map; + } + + /** + * Construct map of key names for an entity type + * @param {object} type Entity type object + * @return {object} Map of key names + */ + function keyMap(type) { + const map = {}; + if (type.$Kind == 'EntityType') { + const keys = getKey(type) || []; + keys.forEach(key => { + if (typeof key == 'string') + map[key] = true; + }); + } + return map; + } + + /** + * Key for path item + * @param {object} entityType Entity Type object + * @return {array} Key of entity type or null + */ + function getKey(entityType) { + let type = entityType; + let keys = null; + while (type) { + keys = type.$Key; + if (keys || !type.$BaseType) break; + type = modelElement(type.$BaseType); + } + return keys; + } + + /** + * Key for path item + * @param {object} entityType Entity Type object + * @param {integer} level Number of navigation segments so far + * @return {object} key: Key segment, parameters: key parameters + */ + function entityKey(entityType, level) { + let segment = ''; + const params = []; + const keys = getKey(entityType) || []; + const properties = propertiesOfStructuredType(entityType); + + keys.forEach((key, index) => { + const suffix = level > 0 ? '_' + level : ''; + if (keyAsSegment) + segment += '/'; + else { + if (index > 0) segment += ','; + if (keys.length != 1) segment += key + '='; + } + let parameter; + let property = {}; + if (typeof key == 'string') { + parameter = key; + property = properties[key]; + } else { + parameter = Object.keys(key)[0]; + const segments = key[parameter].split('/'); + property = properties[segments[0]]; + for (let i = 1; i < segments.length; i++) { + const complexType = modelElement(property.$Type); + const properties = propertiesOfStructuredType(complexType); + property = properties[segments[i]]; + } + } + const propertyType = property.$Type; + segment += pathValuePrefix(propertyType, keyAsSegment) + '{' + parameter + suffix + '}' + pathValueSuffix(propertyType, keyAsSegment); + const param = { + description: [property[voc.Core.Description], property[voc.Core.LongDescription]].filter(t => t).join(' \n') + || 'key: ' + parameter, + in: 'path', + name: parameter + suffix, + required: true, + schema: getSchema(property, '', true) + }; + params.push(param); + }) + return { segment: (keyAsSegment ? '' : '(') + segment + (keyAsSegment ? '' : ')'), parameters: params }; + } + + + /** * Add path and Path Item Object for actions and functions bound to the element * @param {object} paths Paths Object to augment @@ -208,7 +1652,7 @@ const { SUFFIX, TITLE_SUFFIX, SYSTEM_QUERY_OPTIONS, ODM_ANNOTATIONS, ER_ANNOTATI + 'URL-encoded JSON ' + (p.$Collection ? 'array with items ' : '') + 'of type ' - + namespaceQualifiedName(p.$Type || 'Edm.String') + + namespaceQualifiedName(p.$Type || 'Edm.String', namespace) + ', see [Complex and Collection Literals](https://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part2-url-conventions.html#sec_ComplexandCollectionLiterals)'; param.example = p.$Collection ? '[]' : '{}'; } else { @@ -954,12 +2398,12 @@ const { SUFFIX, TITLE_SUFFIX, SYSTEM_QUERY_OPTIONS, ODM_ANNOTATIONS, ER_ANNOTATI if (forFunction) { if (s.example && typeof s.example === "string") { - s.example = `${pathValuePrefix(element.$Type)}${s.example - }${pathValueSuffix(element.$Type)} `; + s.example = `${pathValuePrefix(element.$Type, keyAsSegment)}${s.example + }${pathValueSuffix(element.$Type, keyAsSegment)} `; } if (s.pattern) { - const pre = pathValuePrefix(element.$Type); - const suf = pathValueSuffix(element.$Type); + const pre = pathValuePrefix(element.$Type, keyAsSegment); + const suf = pathValueSuffix(element.$Type, keyAsSegment); s.pattern = s.pattern.replace(/^\^/, `^ ${pre} (`); s.pattern = s.pattern.replace(/\$$/, `)${suf} $`); } else if (!element.$Type || element.$Type === "Edm.String") { @@ -1156,37 +2600,6 @@ const { SUFFIX, TITLE_SUFFIX, SYSTEM_QUERY_OPTIONS, ODM_ANNOTATIONS, ER_ANNOTATI }); } - /** - * a qualified name consists of a namespace or alias, a dot, and a simple name - * @param {string} qualifiedName - * @return {string} namespace-qualified name - */ - function namespaceQualifiedName(qualifiedName) { - let np = nameParts(qualifiedName); - return namespace[np.qualifier] + '.' + np.name; - } - /** - * a qualified name consists of a namespace or alias, a dot, and a simple name - * @param {string} qualifiedName - * @return {object} with components qualifier and name - */ - function nameParts(qualifiedName) { - const pos = qualifiedName.lastIndexOf('.'); - console.assert(pos > 0, 'Invalid qualified name ' + qualifiedName); - return { - qualifier: qualifiedName.substring(0, pos), - name: qualifiedName.substring(pos + 1) - }; - } - - /** - * an identifier does not start with $ and does not contain @ - * @param {string} name - * @return {boolean} name is an identifier - */ - function isIdentifier(name) { - return !name.startsWith('$') && !name.includes('@'); - } }; diff --git a/package.json b/package.json index e2f4139..301c68e 100644 --- a/package.json +++ b/package.json @@ -38,6 +38,7 @@ "@sap/cds": ">=7.6" }, "devDependencies": { + "@sap/cds": "^9.2.1", "@types/jest": "^30.0.0", "@types/node": "^24.3.0", "@types/pluralize": "^0.0.33", From 93742e1bad59302f899c14bd64ea1ca25c78b0b7 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Fri, 29 Aug 2025 16:54:36 +0000 Subject: [PATCH 3/3] Refactor csdl2openapi: Modularize imports and improve namespace handling Co-authored-by: web.88002 --- dist/lib/compile/csdl2openapi.d.ts.map | 2 +- dist/lib/compile/csdl2openapi.js | 75 +---- dist/lib/compile/csdl2openapi.js.map | 2 +- dist/lib/compile/modules/builders/index.d.ts | 37 +++ .../compile/modules/builders/index.d.ts.map | 1 + dist/lib/compile/modules/builders/index.js | 15 + .../lib/compile/modules/builders/index.js.map | 1 + .../compile/modules/builders/parameters.d.ts | 96 ++++++ .../modules/builders/parameters.d.ts.map | 1 + .../compile/modules/builders/parameters.js | 303 ++++++++++++++++++ .../modules/builders/parameters.js.map | 1 + dist/lib/compile/modules/builders/paths.d.ts | 86 +++++ .../compile/modules/builders/paths.d.ts.map | 1 + dist/lib/compile/modules/builders/paths.js | 279 ++++++++++++++++ .../lib/compile/modules/builders/paths.js.map | 1 + .../compile/modules/builders/responses.d.ts | 65 ++++ .../modules/builders/responses.d.ts.map | 1 + .../lib/compile/modules/builders/responses.js | 266 +++++++++++++++ .../compile/modules/builders/responses.js.map | 1 + dist/lib/compile/modules/utils/naming.d.ts | 6 + .../lib/compile/modules/utils/naming.d.ts.map | 2 +- dist/lib/compile/modules/utils/naming.js | 14 +- dist/lib/compile/modules/utils/naming.js.map | 2 +- 23 files changed, 1188 insertions(+), 70 deletions(-) create mode 100644 dist/lib/compile/modules/builders/index.d.ts create mode 100644 dist/lib/compile/modules/builders/index.d.ts.map create mode 100644 dist/lib/compile/modules/builders/index.js create mode 100644 dist/lib/compile/modules/builders/index.js.map create mode 100644 dist/lib/compile/modules/builders/parameters.d.ts create mode 100644 dist/lib/compile/modules/builders/parameters.d.ts.map create mode 100644 dist/lib/compile/modules/builders/parameters.js create mode 100644 dist/lib/compile/modules/builders/parameters.js.map create mode 100644 dist/lib/compile/modules/builders/paths.d.ts create mode 100644 dist/lib/compile/modules/builders/paths.d.ts.map create mode 100644 dist/lib/compile/modules/builders/paths.js create mode 100644 dist/lib/compile/modules/builders/paths.js.map create mode 100644 dist/lib/compile/modules/builders/responses.d.ts create mode 100644 dist/lib/compile/modules/builders/responses.d.ts.map create mode 100644 dist/lib/compile/modules/builders/responses.js create mode 100644 dist/lib/compile/modules/builders/responses.js.map diff --git a/dist/lib/compile/csdl2openapi.d.ts.map b/dist/lib/compile/csdl2openapi.d.ts.map index 1ed3f5a..57fde82 100644 --- a/dist/lib/compile/csdl2openapi.d.ts.map +++ b/dist/lib/compile/csdl2openapi.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"csdl2openapi.d.ts","sourceRoot":"","sources":["../../../lib/compile/csdl2openapi.js"],"names":[],"mappings":"AAsC8B,mCAJnB,MAAM,qKACN,MAAM,GACL,MAAM,CA4hFjB"} \ No newline at end of file +{"version":3,"file":"csdl2openapi.d.ts","sourceRoot":"","sources":["../../../lib/compile/csdl2openapi.js"],"names":[],"mappings":"AAyE8B,mCAJnB,MAAM,qKACN,MAAM,GACL,MAAM,CAq+EjB"} \ No newline at end of file diff --git a/dist/lib/compile/csdl2openapi.js b/dist/lib/compile/csdl2openapi.js index 26f858a..c99ede8 100644 --- a/dist/lib/compile/csdl2openapi.js +++ b/dist/lib/compile/csdl2openapi.js @@ -7,8 +7,11 @@ var pluralize = require('pluralize'); const DEBUG = cds.debug('openapi'); // Initialize cds.debug with the 'openapi' // Import modularized components const constants = require('./modules/constants'); -const { nameParts, isIdentifier, splitName, namespaceQualifiedName } = require('./modules/utils/naming'); +const { nameParts, isIdentifier, splitName, namespaceQualifiedName, enumMember } = require('./modules/utils/naming'); const validators = require('./modules/validators'); +const { pathValuePrefix, pathValueSuffix, navigationPropertyPath, propertyPath, navigationPaths, navigationPathMap, primitivePaths, buildKeyParameters, buildPathWithKeys } = require('./modules/builders/paths'); +const { addQueryOptions, optionTop, optionSkip, optionCount, optionFilter, optionOrderBy, optionSearch, optionSelect, optionExpand, buildComponentParameters } = require('./modules/builders/parameters'); +const { collectionResponse, entityResponse, operationResponse, errorResponse, countResponse, batchResponse, buildStandardResponses, getTypeSchema, getEdmTypeSchema, withETag } = require('./modules/builders/responses'); //TODO // - Core.Example for complex types // - reduce number of loops over schemas @@ -212,7 +215,7 @@ module.exports.csdl2openapi = function (csdl, { url: serviceRoot, servers: serve }); } else if (element.$BaseType) { - const base = namespaceQualifiedName(element.$BaseType); + const base = namespaceQualifiedName(element.$BaseType, namespace); if (!derivedTypes[base]) derivedTypes[base] = []; derivedTypes[base].push(qualifiedName); @@ -1359,7 +1362,7 @@ see [Expand](http://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part1-prot } } const propertyType = property.$Type; - segment += pathValuePrefix(propertyType) + '{' + parameter + suffix + '}' + pathValueSuffix(propertyType); + segment += pathValuePrefix(propertyType, keyAsSegment) + '{' + parameter + suffix + '}' + pathValueSuffix(propertyType, keyAsSegment); const param = { description: [property[voc.Core.Description], property[voc.Core.LongDescription]].filter(t => t).join(' \n') || 'key: ' + parameter, @@ -1372,34 +1375,6 @@ see [Expand](http://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part1-prot }); return { segment: (keyAsSegment ? '' : '(') + segment + (keyAsSegment ? '' : ')'), parameters: params }; } - /** - * Prefix for key value in key segment - * @param {typename} Qualified name of key property type - * @return {string} value prefix - */ - function pathValuePrefix(typename) { - //TODO: handle other Edm types, enumeration types, and type definitions - if (['Edm.Int64', 'Edm.Int32', 'Edm.Int16', 'Edm.SByte', 'Edm.Byte', - 'Edm.Double', 'Edm.Single', 'Edm.Date', 'Edm.DateTimeOffset', 'Edm.Guid'].includes(typename)) - return ''; - if (keyAsSegment) - return ''; - return `'`; - } - /** - * Suffix for key value in key segment - * @param {typename} Qualified name of key property type - * @return {string} value prefix - */ - function pathValueSuffix(typename) { - //TODO: handle other Edm types, enumeration types, and type definitions - if (['Edm.Int64', 'Edm.Int32', 'Edm.Int16', 'Edm.SByte', 'Edm.Byte', - 'Edm.Double', 'Edm.Single', 'Edm.Date', 'Edm.DateTimeOffset', 'Edm.Guid'].includes(typename)) - return ''; - if (keyAsSegment) - return ''; - return `'`; - } /** * Add path and Path Item Object for actions and functions bound to the element * @param {object} paths Paths Object to augment @@ -1546,7 +1521,7 @@ see [Expand](http://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part1-prot + 'URL-encoded JSON ' + (p.$Collection ? 'array with items ' : '') + 'of type ' - + namespaceQualifiedName(p.$Type || 'Edm.String') + + namespaceQualifiedName(p.$Type || 'Edm.String', namespace) + ', see [Complex and Collection Literals](https://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part2-url-conventions.html#sec_ComplexandCollectionLiterals)'; param.example = p.$Collection ? '[]' : '{}'; } @@ -2270,11 +2245,11 @@ see [Expand](http://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part1-prot } if (forFunction) { if (s.example && typeof s.example === "string") { - s.example = `${pathValuePrefix(element.$Type)}${s.example}${pathValueSuffix(element.$Type)} `; + s.example = `${pathValuePrefix(element.$Type, keyAsSegment)}${s.example}${pathValueSuffix(element.$Type, keyAsSegment)} `; } if (s.pattern) { - const pre = pathValuePrefix(element.$Type); - const suf = pathValueSuffix(element.$Type); + const pre = pathValuePrefix(element.$Type, keyAsSegment); + const suf = pathValueSuffix(element.$Type, keyAsSegment); s.pattern = s.pattern.replace(/^\^/, `^ ${pre} (`); s.pattern = s.pattern.replace(/\$$/, `)${suf} $`); } @@ -2475,35 +2450,5 @@ see [Expand](http://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part1-prot openapi.security.push(s); }); } - /** - * a qualified name consists of a namespace or alias, a dot, and a simple name - * @param {string} qualifiedName - * @return {string} namespace-qualified name - */ - function namespaceQualifiedName(qualifiedName) { - let np = nameParts(qualifiedName); - return namespace[np.qualifier] + '.' + np.name; - } - /** - * a qualified name consists of a namespace or alias, a dot, and a simple name - * @param {string} qualifiedName - * @return {object} with components qualifier and name - */ - function nameParts(qualifiedName) { - const pos = qualifiedName.lastIndexOf('.'); - console.assert(pos > 0, 'Invalid qualified name ' + qualifiedName); - return { - qualifier: qualifiedName.substring(0, pos), - name: qualifiedName.substring(pos + 1) - }; - } - /** - * an identifier does not start with $ and does not contain @ - * @param {string} name - * @return {boolean} name is an identifier - */ - function isIdentifier(name) { - return !name.startsWith('$') && !name.includes('@'); - } }; //# sourceMappingURL=csdl2openapi.js.map \ No newline at end of file diff --git a/dist/lib/compile/csdl2openapi.js.map b/dist/lib/compile/csdl2openapi.js.map index d0cfb52..2c334f5 100644 --- a/dist/lib/compile/csdl2openapi.js.map +++ b/dist/lib/compile/csdl2openapi.js.map @@ -1 +1 @@ -{"version":3,"file":"csdl2openapi.js","sourceRoot":"","sources":["../../../lib/compile/csdl2openapi.js"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"csdl2openapi.js","sourceRoot":"","sources":["../../../lib/compile/csdl2openapi.js"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/lib/compile/modules/builders/index.d.ts b/dist/lib/compile/modules/builders/index.d.ts new file mode 100644 index 0000000..871283b --- /dev/null +++ b/dist/lib/compile/modules/builders/index.d.ts @@ -0,0 +1,37 @@ +declare const _exports: { + collectionResponse: typeof responses.collectionResponse; + entityResponse: typeof responses.entityResponse; + operationResponse: typeof responses.operationResponse; + errorResponse: typeof responses.errorResponse; + countResponse: typeof responses.countResponse; + batchResponse: typeof responses.batchResponse; + buildStandardResponses: typeof responses.buildStandardResponses; + getTypeSchema: typeof responses.getTypeSchema; + getEdmTypeSchema: typeof responses.getEdmTypeSchema; + withETag: typeof responses.withETag; + addQueryOptions: typeof parameters.addQueryOptions; + optionTop: typeof parameters.optionTop; + optionSkip: typeof parameters.optionSkip; + optionCount: typeof parameters.optionCount; + optionFilter: typeof parameters.optionFilter; + optionOrderBy: typeof parameters.optionOrderBy; + optionSearch: typeof parameters.optionSearch; + optionSelect: typeof parameters.optionSelect; + optionExpand: typeof parameters.optionExpand; + buildComponentParameters: typeof parameters.buildComponentParameters; + pathValuePrefix: typeof paths.pathValuePrefix; + pathValueSuffix: typeof paths.pathValueSuffix; + navigationPropertyPath: typeof paths.navigationPropertyPath; + propertyPath: typeof paths.propertyPath; + navigationPaths: typeof paths.navigationPaths; + navigationPathMap: typeof paths.navigationPathMap; + primitivePaths: typeof paths.primitivePaths; + entryToProperty: typeof paths.entryToProperty; + buildKeyParameters: typeof paths.buildKeyParameters; + buildPathWithKeys: typeof paths.buildPathWithKeys; +}; +export = _exports; +import responses = require("./responses"); +import parameters = require("./parameters"); +import paths = require("./paths"); +//# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/dist/lib/compile/modules/builders/index.d.ts.map b/dist/lib/compile/modules/builders/index.d.ts.map new file mode 100644 index 0000000..8ffc3d6 --- /dev/null +++ b/dist/lib/compile/modules/builders/index.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../lib/compile/modules/builders/index.js"],"names":[],"mappings":""} \ No newline at end of file diff --git a/dist/lib/compile/modules/builders/index.js b/dist/lib/compile/modules/builders/index.js new file mode 100644 index 0000000..63aa523 --- /dev/null +++ b/dist/lib/compile/modules/builders/index.js @@ -0,0 +1,15 @@ +"use strict"; +/** + * Builder modules index + * + * Re-exports all builder modules for convenient access + */ +const paths = require('./paths'); +const parameters = require('./parameters'); +const responses = require('./responses'); +module.exports = { + ...paths, + ...parameters, + ...responses +}; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/dist/lib/compile/modules/builders/index.js.map b/dist/lib/compile/modules/builders/index.js.map new file mode 100644 index 0000000..9a61900 --- /dev/null +++ b/dist/lib/compile/modules/builders/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../lib/compile/modules/builders/index.js"],"names":[],"mappings":";AAAA;;;;GAIG;AAEH,MAAM,KAAK,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;AACjC,MAAM,UAAU,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;AAC3C,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;AAEzC,MAAM,CAAC,OAAO,GAAG;IACb,GAAG,KAAK;IACR,GAAG,UAAU;IACb,GAAG,SAAS;CACf,CAAC"} \ No newline at end of file diff --git a/dist/lib/compile/modules/builders/parameters.d.ts b/dist/lib/compile/modules/builders/parameters.d.ts new file mode 100644 index 0000000..7f0c977 --- /dev/null +++ b/dist/lib/compile/modules/builders/parameters.d.ts @@ -0,0 +1,96 @@ +/** + * Add standard OData query parameters to a path + * @param {Array} parameters - Array of parameters to augment + * @param {object} element - Model element + * @param {object} modelElement - Function to get model element + * @param {object} propertiesOfStructuredType - Function to get properties + * @param {object} root - Root entity set + * @param {string} navigationPath - Navigation path for restrictions + * @param {object} target - Target container child + * @param {object} restrictions - Navigation restrictions + * @param {object} options - Options including queryOptionPrefix + */ +export function addQueryOptions(parameters: any[], element: object, modelElement: object, propertiesOfStructuredType: object, root: object, navigationPath: string, target: object, restrictions: object, options?: object): void; +/** + * Add parameter for query option $top + * @param {Array} parameters - Array of parameters to augment + * @param {object} restrictions - Navigation property restrictions + * @param {string} queryOptionPrefix - Query option prefix + */ +export function optionTop(parameters: any[], restrictions: object, queryOptionPrefix?: string): void; +/** + * Add parameter for query option $skip + * @param {Array} parameters - Array of parameters to augment + * @param {object} restrictions - Navigation property restrictions + * @param {string} queryOptionPrefix - Query option prefix + */ +export function optionSkip(parameters: any[], restrictions: object, queryOptionPrefix?: string): void; +/** + * Add parameter for query option $count + * @param {Array} parameters - Array of parameters to augment + * @param {object} restrictions - Navigation property restrictions + * @param {string} target - Target container child + * @param {string} queryOptionPrefix - Query option prefix + */ +export function optionCount(parameters: any[], restrictions: object, target: string, queryOptionPrefix?: string): void; +/** + * Add parameter for query option $filter + * @param {Array} parameters - Array of parameters to augment + * @param {object} element - Model element + * @param {Function} modelElement - Function to get model element + * @param {Function} propertiesOfStructuredType - Function to get properties + * @param {string} target - Target container child + * @param {object} restrictions - Navigation property restrictions + * @param {string} queryOptionPrefix - Query option prefix + */ +export function optionFilter(parameters: any[], element: object, modelElement: Function, propertiesOfStructuredType: Function, target: string, restrictions: object, queryOptionPrefix?: string): void; +/** + * Add parameter for query option $orderby + * @param {Array} parameters - Array of parameters to augment + * @param {object} element - Model element of navigation segment + * @param {Function} modelElement - Function to get model element + * @param {Function} propertiesOfStructuredType - Function to get properties + * @param {string} target - Target container child of path + * @param {object} restrictions - Navigation property restrictions of navigation segment + * @param {string} queryOptionPrefix - Query option prefix + */ +export function optionOrderBy(parameters: any[], element: object, modelElement: Function, propertiesOfStructuredType: Function, target: string, restrictions: object, queryOptionPrefix?: string): void; +/** + * Add parameter for query option $search + * @param {Array} parameters - Array of parameters to augment + * @param {string} target - Target container child of path + * @param {object} restrictions - Navigation property restrictions of navigation segment + * @param {string} queryOptionPrefix - Query option prefix + */ +export function optionSearch(parameters: any[], target: string, restrictions: object, queryOptionPrefix?: string): void; +/** + * Add parameter for query option $select + * @param {Array} parameters - Array of parameters to augment + * @param {object} element - Model element + * @param {Function} modelElement - Function to get model element + * @param {Function} propertiesOfStructuredType - Function to get properties + * @param {object} restrictions - Navigation property restrictions + * @param {object} nonExpandable - Non-expandable properties + * @param {string} queryOptionPrefix - Query option prefix + */ +export function optionSelect(parameters: any[], element: object, modelElement: Function, propertiesOfStructuredType: Function, restrictions: object, nonExpandable: object, queryOptionPrefix?: string): void; +/** + * Add parameter for query option $expand + * @param {Array} parameters - Array of parameters to augment + * @param {object} element - Model element + * @param {Function} modelElement - Function to get model element + * @param {Function} navigationPaths - Function to get navigation paths + * @param {object} restrictions - Navigation property restrictions + * @param {object} nonExpandable - Non-expandable properties + * @param {number} level - Navigation level + * @param {number} maxLevels - Maximum levels + * @param {string} queryOptionPrefix - Query option prefix + */ +export function optionExpand(parameters: any[], element: object, modelElement: Function, navigationPaths: Function, restrictions: object, nonExpandable: object, level: number, maxLevels: number, queryOptionPrefix?: string): void; +/** + * Build standard OData component parameters + * @param {object} options - Options including queryOptionPrefix + * @return {object} Component parameters object + */ +export function buildComponentParameters(options?: object): object; +//# sourceMappingURL=parameters.d.ts.map \ No newline at end of file diff --git a/dist/lib/compile/modules/builders/parameters.d.ts.map b/dist/lib/compile/modules/builders/parameters.d.ts.map new file mode 100644 index 0000000..5aaa65e --- /dev/null +++ b/dist/lib/compile/modules/builders/parameters.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"parameters.d.ts","sourceRoot":"","sources":["../../../../../lib/compile/modules/builders/parameters.js"],"names":[],"mappings":"AAcA;;;;;;;;;;;GAWG;AACH,4DATW,MAAM,gBACN,MAAM,8BACN,MAAM,QACN,MAAM,kBACN,MAAM,UACN,MAAM,gBACN,MAAM,YACN,MAAM,QAYhB;AAED;;;;;GAKG;AACH,2DAHW,MAAM,sBACN,MAAM,QAMhB;AAED;;;;;GAKG;AACH,4DAHW,MAAM,sBACN,MAAM,QAMhB;AAED;;;;;;GAMG;AACH,6DAJW,MAAM,UACN,MAAM,sBACN,MAAM,QAQhB;AAED;;;;;;;;;GASG;AACH,yDAPW,MAAM,wEAGN,MAAM,gBACN,MAAM,sBACN,MAAM,QA4BhB;AAED;;;;;;;;;GASG;AACH,0DAPW,MAAM,wEAGN,MAAM,gBACN,MAAM,sBACN,MAAM,QAmChB;AAED;;;;;;GAMG;AACH,wDAJW,MAAM,gBACN,MAAM,sBACN,MAAM,QAiBhB;AAED;;;;;;;;;GASG;AACH,yDAPW,MAAM,8EAGN,MAAM,iBACN,MAAM,sBACN,MAAM,QAyChB;AAED;;;;;;;;;;;GAWG;AACH,yDATW,MAAM,mEAGN,MAAM,iBACN,MAAM,SACN,MAAM,aACN,MAAM,sBACN,MAAM,QA0BhB;AAED;;;;GAIG;AACH,mDAHW,MAAM,GACL,MAAM,CA0CjB"} \ No newline at end of file diff --git a/dist/lib/compile/modules/builders/parameters.js b/dist/lib/compile/modules/builders/parameters.js new file mode 100644 index 0000000..3de4da4 --- /dev/null +++ b/dist/lib/compile/modules/builders/parameters.js @@ -0,0 +1,303 @@ +"use strict"; +/** + * Parameter Building Module + * + * This module contains all functions related to building OpenAPI parameters + * from CDS model elements. + */ +const { propertyPath, primitivePaths } = require('./paths'); +const { enumMember } = require('../utils/naming'); +const { Logger } = require('../utils/logger'); +const logger = new Logger('csdl2openapi:parameters'); +const DEBUG = logger.debug.bind(logger); +/** + * Add standard OData query parameters to a path + * @param {Array} parameters - Array of parameters to augment + * @param {object} element - Model element + * @param {object} modelElement - Function to get model element + * @param {object} propertiesOfStructuredType - Function to get properties + * @param {object} root - Root entity set + * @param {string} navigationPath - Navigation path for restrictions + * @param {object} target - Target container child + * @param {object} restrictions - Navigation restrictions + * @param {object} options - Options including queryOptionPrefix + */ +function addQueryOptions(parameters, element, modelElement, propertiesOfStructuredType, root, navigationPath, target, restrictions, options = {}) { + const { queryOptionPrefix = '$' } = options; + // Add standard query options + optionTop(parameters, restrictions, queryOptionPrefix); + optionSkip(parameters, restrictions, queryOptionPrefix); + optionCount(parameters, restrictions, target, queryOptionPrefix); + optionFilter(parameters, element, modelElement, propertiesOfStructuredType, target, restrictions, queryOptionPrefix); + optionOrderBy(parameters, element, modelElement, propertiesOfStructuredType, target, restrictions, queryOptionPrefix); + optionSearch(parameters, target, restrictions, queryOptionPrefix); +} +/** + * Add parameter for query option $top + * @param {Array} parameters - Array of parameters to augment + * @param {object} restrictions - Navigation property restrictions + * @param {string} queryOptionPrefix - Query option prefix + */ +function optionTop(parameters, restrictions, queryOptionPrefix = '$') { + if (restrictions.TopSupported !== false) { + parameters.push({ $ref: '#/components/parameters/top' }); + } +} +/** + * Add parameter for query option $skip + * @param {Array} parameters - Array of parameters to augment + * @param {object} restrictions - Navigation property restrictions + * @param {string} queryOptionPrefix - Query option prefix + */ +function optionSkip(parameters, restrictions, queryOptionPrefix = '$') { + if (restrictions.SkipSupported !== false) { + parameters.push({ $ref: '#/components/parameters/skip' }); + } +} +/** + * Add parameter for query option $count + * @param {Array} parameters - Array of parameters to augment + * @param {object} restrictions - Navigation property restrictions + * @param {string} target - Target container child + * @param {string} queryOptionPrefix - Query option prefix + */ +function optionCount(parameters, restrictions, target, queryOptionPrefix = '$') { + const countRestrictions = restrictions.CountRestrictions || (target && target['Org.OData.Capabilities.V1.CountRestrictions']) || {}; + if (countRestrictions.Countable !== false) { + parameters.push({ $ref: '#/components/parameters/count' }); + } +} +/** + * Add parameter for query option $filter + * @param {Array} parameters - Array of parameters to augment + * @param {object} element - Model element + * @param {Function} modelElement - Function to get model element + * @param {Function} propertiesOfStructuredType - Function to get properties + * @param {string} target - Target container child + * @param {object} restrictions - Navigation property restrictions + * @param {string} queryOptionPrefix - Query option prefix + */ +function optionFilter(parameters, element, modelElement, propertiesOfStructuredType, target, restrictions, queryOptionPrefix = '$') { + const filterRestrictions = restrictions.FilterRestrictions || (target && target['Org.OData.Capabilities.V1.FilterRestrictions']) || {}; + if (filterRestrictions.Filterable !== false) { + const filter = { + name: queryOptionPrefix + 'filter', + description: filterRestrictions['Org.OData.Core.V1.Description'] + || 'Filter items by property values, see [Filtering](http://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part1-protocol.html#sec_SystemQueryOptionfilter)', + in: 'query', + schema: { + type: 'string' + } + }; + if (filterRestrictions.RequiresFilter) + filter.required = true; + if (filterRestrictions.RequiredProperties) { + filter.description += '\n\nRequired filter properties:'; + filterRestrictions.RequiredProperties.forEach(item => filter.description += '\n- ' + propertyPath(item)); + } + parameters.push(filter); + } +} +/** + * Add parameter for query option $orderby + * @param {Array} parameters - Array of parameters to augment + * @param {object} element - Model element of navigation segment + * @param {Function} modelElement - Function to get model element + * @param {Function} propertiesOfStructuredType - Function to get properties + * @param {string} target - Target container child of path + * @param {object} restrictions - Navigation property restrictions of navigation segment + * @param {string} queryOptionPrefix - Query option prefix + */ +function optionOrderBy(parameters, element, modelElement, propertiesOfStructuredType, target, restrictions, queryOptionPrefix = '$') { + const sortRestrictions = restrictions.SortRestrictions || (target && target['Org.OData.Capabilities.V1.SortRestrictions']) || {}; + if (sortRestrictions.Sortable !== false) { + const nonSortable = {}; + (sortRestrictions.NonSortableProperties || []).forEach(name => { + nonSortable[propertyPath(name)] = true; + }); + const orderbyItems = []; + primitivePaths(element, modelElement, propertiesOfStructuredType).filter(property => !nonSortable[property]).forEach(property => { + orderbyItems.push(property); + orderbyItems.push(property + ' desc'); + }); + if (orderbyItems.length > 0) { + parameters.push({ + name: queryOptionPrefix + 'orderby', + description: sortRestrictions['Org.OData.Core.V1.Description'] + || 'Order items by property values, see [Sorting](http://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part1-protocol.html#sec_SystemQueryOptionorderby)', + in: 'query', + explode: false, + schema: { + type: 'array', + uniqueItems: true, + items: { + type: 'string', + enum: orderbyItems + } + } + }); + } + } +} +/** + * Add parameter for query option $search + * @param {Array} parameters - Array of parameters to augment + * @param {string} target - Target container child of path + * @param {object} restrictions - Navigation property restrictions of navigation segment + * @param {string} queryOptionPrefix - Query option prefix + */ +function optionSearch(parameters, target, restrictions, queryOptionPrefix = '$') { + const searchRestrictions = restrictions.SearchRestrictions || (target && target['Org.OData.Capabilities.V1.SearchRestrictions']) || {}; + if (searchRestrictions.Searchable !== false) { + if (searchRestrictions['Org.OData.Core.V1.Description']) { + parameters.push({ + name: queryOptionPrefix + 'search', + description: searchRestrictions['Org.OData.Core.V1.Description'], + in: 'query', + schema: { type: 'string' } + }); + } + else { + parameters.push({ $ref: '#/components/parameters/search' }); + } + } +} +/** + * Add parameter for query option $select + * @param {Array} parameters - Array of parameters to augment + * @param {object} element - Model element + * @param {Function} modelElement - Function to get model element + * @param {Function} propertiesOfStructuredType - Function to get properties + * @param {object} restrictions - Navigation property restrictions + * @param {object} nonExpandable - Non-expandable properties + * @param {string} queryOptionPrefix - Query option prefix + */ +function optionSelect(parameters, element, modelElement, propertiesOfStructuredType, restrictions, nonExpandable, queryOptionPrefix = '$') { + const selectSupport = restrictions.SelectSupport || {}; + if (selectSupport.Supported !== false) { + const selectItems = []; + // Add primitive properties + primitivePaths(element, modelElement, propertiesOfStructuredType).forEach(path => { + selectItems.push(path); + }); + // Add navigation properties if allowed + if (selectSupport.Expandable !== false) { + const type = modelElement(element.$Type); + const properties = propertiesOfStructuredType(type); + Object.keys(properties).forEach(key => { + if (properties[key].$Kind === 'NavigationProperty' && !nonExpandable[key]) { + selectItems.push(key); + } + }); + } + if (selectItems.length > 0) { + parameters.push({ + name: queryOptionPrefix + 'select', + description: 'Select properties to be returned, see [Select](http://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part1-protocol.html#sec_SystemQueryOptionselect)', + in: 'query', + explode: false, + schema: { + type: 'array', + uniqueItems: true, + items: { + type: 'string', + enum: selectItems + } + } + }); + } + } +} +/** + * Add parameter for query option $expand + * @param {Array} parameters - Array of parameters to augment + * @param {object} element - Model element + * @param {Function} modelElement - Function to get model element + * @param {Function} navigationPaths - Function to get navigation paths + * @param {object} restrictions - Navigation property restrictions + * @param {object} nonExpandable - Non-expandable properties + * @param {number} level - Navigation level + * @param {number} maxLevels - Maximum levels + * @param {string} queryOptionPrefix - Query option prefix + */ +function optionExpand(parameters, element, modelElement, navigationPaths, restrictions, nonExpandable, level, maxLevels, queryOptionPrefix = '$') { + const expandRestrictions = restrictions.ExpandRestrictions || {}; + if (expandRestrictions.Expandable !== false && level < maxLevels) { + const paths = navigationPaths(element, modelElement, maxLevels); + const expandItems = paths.filter(path => !nonExpandable[path]); + if (expandItems.length > 0) { + parameters.push({ + name: queryOptionPrefix + 'expand', + description: 'Expand related entities, see [Expand](http://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part1-protocol.html#sec_SystemQueryOptionexpand)', + in: 'query', + explode: false, + schema: { + type: 'array', + uniqueItems: true, + items: { + type: 'string', + enum: expandItems + } + } + }); + } + } +} +/** + * Build standard OData component parameters + * @param {object} options - Options including queryOptionPrefix + * @return {object} Component parameters object + */ +function buildComponentParameters(options = {}) { + const { queryOptionPrefix = '$' } = options; + return { + top: { + name: queryOptionPrefix + 'top', + description: 'Show only the first n items, see [Paging - Top](http://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part1-protocol.html#sec_SystemQueryOptiontop)', + in: 'query', + schema: { + type: 'integer', + minimum: 0 + }, + example: 50 + }, + skip: { + name: queryOptionPrefix + 'skip', + description: 'Skip the first n items, see [Paging - Skip](http://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part1-protocol.html#sec_SystemQueryOptionskip)', + in: 'query', + schema: { + type: 'integer', + minimum: 0 + } + }, + count: { + name: queryOptionPrefix + 'count', + description: 'Include count of items, see [Count](http://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part1-protocol.html#sec_SystemQueryOptioncount)', + in: 'query', + schema: { + type: 'boolean' + } + }, + search: { + name: queryOptionPrefix + 'search', + description: 'Search items by search phrases, see [Searching](http://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part1-protocol.html#sec_SystemQueryOptionsearch)', + in: 'query', + schema: { + type: 'string' + } + } + }; +} +module.exports = { + addQueryOptions, + optionTop, + optionSkip, + optionCount, + optionFilter, + optionOrderBy, + optionSearch, + optionSelect, + optionExpand, + buildComponentParameters +}; +//# sourceMappingURL=parameters.js.map \ No newline at end of file diff --git a/dist/lib/compile/modules/builders/parameters.js.map b/dist/lib/compile/modules/builders/parameters.js.map new file mode 100644 index 0000000..ca415a5 --- /dev/null +++ b/dist/lib/compile/modules/builders/parameters.js.map @@ -0,0 +1 @@ +{"version":3,"file":"parameters.js","sourceRoot":"","sources":["../../../../../lib/compile/modules/builders/parameters.js"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/lib/compile/modules/builders/paths.d.ts b/dist/lib/compile/modules/builders/paths.d.ts new file mode 100644 index 0000000..8c50a9c --- /dev/null +++ b/dist/lib/compile/modules/builders/paths.d.ts @@ -0,0 +1,86 @@ +/** + * Extract path value prefix based on type + * @param {string} typename - The type name + * @param {boolean} keyAsSegment - Whether key is used as segment + * @return {string} value prefix + */ +export function pathValuePrefix(typename: string, keyAsSegment: boolean): string; +/** + * Extract path value suffix based on type + * @param {string} typename - The type name + * @param {boolean} keyAsSegment - Whether key is used as segment + * @return {string} value suffix + */ +export function pathValueSuffix(typename: string, keyAsSegment: boolean): string; +/** + * Unpack NavigationPropertyPath value if it uses CSDL JSON CS01 style + * @param {string|object} path - Qualified name of referenced type + * @return {string} Navigation property path + */ +export function navigationPropertyPath(path: string | object): string; +/** + * Unpack PropertyPath value if it uses CSDL JSON CS01 style + * @param {string|object} path - Qualified name of referenced type + * @return {string} Property path + */ +export function propertyPath(path: string | object): string; +/** + * Build navigation paths from element + * @param {object} element - Model element + * @param {Function} modelElement - Function to get model element + * @param {Function} propertiesOfStructuredType - Function to get properties + * @param {string} prefix - Path prefix + * @param {number} level - Navigation level + * @param {number} maxLevels - Maximum navigation levels + * @return {Array} Array of navigation property paths + */ +export function navigationPaths(element: object, modelElement: Function, propertiesOfStructuredType: Function, prefix: string | undefined, level: number | undefined, maxLevels: number): any[]; +/** + * Create a map of navigation property paths and their types + * @param {object} type - Type to analyze + * @param {Function} propertiesOfStructuredType - Function to get properties + * @param {Function} modelElement - Function to get model element + * @param {object} map - Map to populate + * @param {string} prefix - Path prefix + * @param {number} level - Current level + * @param {number} maxLevels - Maximum levels + * @return {object} Map of navigation property paths and their types + */ +export function navigationPathMap(type: object, propertiesOfStructuredType: Function, modelElement: Function, map: object | undefined, prefix: string | undefined, level: number | undefined, maxLevels: number): object; +/** + * Collect primitive paths of a navigation segment and its potentially structured components + * @param {object} element - Model element of navigation segment + * @param {Function} modelElement - Function to get model element + * @param {Function} propertiesOfStructuredType - Function to get properties + * @param {string} prefix - Navigation prefix + * @return {Array} Array of primitive property paths + */ +export function primitivePaths(element: object, modelElement: Function, propertiesOfStructuredType: Function, prefix?: string): any[]; +/** + * Helper function to convert entry to property + * @param {object} parent - Parent property + * @param {Function} modelElement - Function to get model element + * @param {Function} propertiesOfStructuredType - Function to get properties + * @return {Function} Function that converts entry to property + */ +export function entryToProperty(parent: object, modelElement: Function, propertiesOfStructuredType: Function): Function; +/** + * Build path parameters for key properties + * @param {object} keyNames - Key property names + * @param {object} properties - Properties of the type + * @param {string} level - Navigation level + * @param {object} options - Options object with keyAsSegment flag + * @return {Array} Array of parameter objects + */ +export function buildKeyParameters(keyNames: object, properties: object, level: string, options?: object): any[]; +/** + * Build path template with key parameters + * @param {string} prefix - Path prefix + * @param {Array} keyNames - Key property names + * @param {object} properties - Properties of the type + * @param {number} level - Navigation level + * @param {object} options - Options including keyAsSegment flag + * @return {string} Path template + */ +export function buildPathWithKeys(prefix: string, keyNames: any[], properties: object, level: number, options?: object): string; +//# sourceMappingURL=paths.d.ts.map \ No newline at end of file diff --git a/dist/lib/compile/modules/builders/paths.d.ts.map b/dist/lib/compile/modules/builders/paths.d.ts.map new file mode 100644 index 0000000..d0e21a9 --- /dev/null +++ b/dist/lib/compile/modules/builders/paths.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../../../../lib/compile/modules/builders/paths.js"],"names":[],"mappings":"AAcA;;;;;GAKG;AACH,0CAJW,MAAM,gBACN,OAAO,GACN,MAAM,CAQjB;AAED;;;;;GAKG;AACH,0CAJW,MAAM,gBACN,OAAO,GACN,MAAM,CAQjB;AAED;;;;GAIG;AACH,6CAHW,MAAM,GAAC,MAAM,GACZ,MAAM,CAOjB;AAED;;;;GAIG;AACH,mCAHW,MAAM,GAAC,MAAM,GACZ,MAAM,CAOjB;AAED;;;;;;;;;GASG;AACH,yCARW,MAAM,wEAGN,MAAM,qBACN,MAAM,yBACN,MAAM,SA4BhB;AAED;;;;;;;;;;GAUG;AACH,wCATW,MAAM,qEAGN,MAAM,sBACN,MAAM,qBACN,MAAM,yBACN,MAAM,GACL,MAAM,CAgBjB;AAED;;;;;;;GAOG;AACH,wCANW,MAAM,yEAGN,MAAM,SAiDhB;AAED;;;;;;GAMG;AACH,wCALW,MAAM,0EA2BhB;AAED;;;;;;;GAOG;AACH,6CANW,MAAM,cACN,MAAM,SACN,MAAM,YACN,MAAM,SA+BhB;AAED;;;;;;;;GAQG;AACH,0CAPW,MAAM,+BAEN,MAAM,SACN,MAAM,YACN,MAAM,GACL,MAAM,CAuBjB"} \ No newline at end of file diff --git a/dist/lib/compile/modules/builders/paths.js b/dist/lib/compile/modules/builders/paths.js new file mode 100644 index 0000000..51a80af --- /dev/null +++ b/dist/lib/compile/modules/builders/paths.js @@ -0,0 +1,279 @@ +"use strict"; +/** + * Path Building Module + * + * This module contains all functions related to building OpenAPI paths + * from CDS model elements. + */ +const { nameParts, isIdentifier } = require('../utils/naming'); +const { assert } = require('../utils/errors'); +const { Logger } = require('../utils/logger'); +const logger = new Logger('csdl2openapi:paths'); +const DEBUG = logger.debug.bind(logger); +/** + * Extract path value prefix based on type + * @param {string} typename - The type name + * @param {boolean} keyAsSegment - Whether key is used as segment + * @return {string} value prefix + */ +function pathValuePrefix(typename, keyAsSegment) { + //TODO: handle other Edm types, enumeration types, and type definitions + if (['Edm.Int64', 'Edm.Int32', 'Edm.Int16', 'Edm.SByte', 'Edm.Byte', + 'Edm.Double', 'Edm.Single', 'Edm.Date', 'Edm.DateTimeOffset', 'Edm.Guid'].includes(typename)) + return ''; + if (keyAsSegment) + return ''; + return `'`; +} +/** + * Extract path value suffix based on type + * @param {string} typename - The type name + * @param {boolean} keyAsSegment - Whether key is used as segment + * @return {string} value suffix + */ +function pathValueSuffix(typename, keyAsSegment) { + //TODO: handle other Edm types, enumeration types, and type definitions + if (['Edm.Int64', 'Edm.Int32', 'Edm.Int16', 'Edm.SByte', 'Edm.Byte', + 'Edm.Double', 'Edm.Single', 'Edm.Date', 'Edm.DateTimeOffset', 'Edm.Guid'].includes(typename)) + return ''; + if (keyAsSegment) + return ''; + return `'`; +} +/** + * Unpack NavigationPropertyPath value if it uses CSDL JSON CS01 style + * @param {string|object} path - Qualified name of referenced type + * @return {string} Navigation property path + */ +function navigationPropertyPath(path) { + if (typeof path == 'string') + return path; + else + return path.$NavigationPropertyPath; +} +/** + * Unpack PropertyPath value if it uses CSDL JSON CS01 style + * @param {string|object} path - Qualified name of referenced type + * @return {string} Property path + */ +function propertyPath(path) { + if (typeof path == 'string') + return path; + else + return path.$PropertyPath; +} +/** + * Build navigation paths from element + * @param {object} element - Model element + * @param {Function} modelElement - Function to get model element + * @param {Function} propertiesOfStructuredType - Function to get properties + * @param {string} prefix - Path prefix + * @param {number} level - Navigation level + * @param {number} maxLevels - Maximum navigation levels + * @return {Array} Array of navigation property paths + */ +function navigationPaths(element, modelElement, propertiesOfStructuredType, prefix = '', level = 0, maxLevels) { + const paths = []; + const type = modelElement(element.$Type); + const properties = propertiesOfStructuredType(type); + Object.keys(properties).forEach(key => { + if (properties[key].$Kind == 'NavigationProperty') { + paths.push(prefix + key); + if (!properties[key].$ContainsTarget && level < maxLevels) { + const target = modelElement(properties[key].$Type); + if (target && target.$Kind == 'EntityType') { + const targetPaths = navigationPaths(target, modelElement, propertiesOfStructuredType, prefix + key + '/', level + 1, maxLevels); + paths.push(...targetPaths); + } + } + } + else if (properties[key].$Type && !properties[key].$Collection && level < maxLevels) { + const complexType = modelElement(properties[key].$Type); + if (complexType && complexType.$Kind == 'ComplexType') { + const complexPaths = navigationPaths({ $Type: properties[key].$Type }, modelElement, propertiesOfStructuredType, prefix + key + '/', level + 1, maxLevels); + paths.push(...complexPaths); + } + } + }); + return paths; +} +/** + * Create a map of navigation property paths and their types + * @param {object} type - Type to analyze + * @param {Function} propertiesOfStructuredType - Function to get properties + * @param {Function} modelElement - Function to get model element + * @param {object} map - Map to populate + * @param {string} prefix - Path prefix + * @param {number} level - Current level + * @param {number} maxLevels - Maximum levels + * @return {object} Map of navigation property paths and their types + */ +function navigationPathMap(type, propertiesOfStructuredType, modelElement, map = {}, prefix = '', level = 0, maxLevels) { + const properties = propertiesOfStructuredType(type); + Object.keys(properties).forEach(key => { + if (properties[key].$Kind == 'NavigationProperty') { + map[prefix + key] = properties[key]; + } + else if (properties[key].$Type && !properties[key].$Collection && level < maxLevels) { + const complexType = modelElement(properties[key].$Type); + if (complexType && complexType.$Kind == 'ComplexType') { + navigationPathMap(complexType, propertiesOfStructuredType, modelElement, map, prefix + key + '/', level + 1, maxLevels); + } + } + }); + return map; +} +/** + * Collect primitive paths of a navigation segment and its potentially structured components + * @param {object} element - Model element of navigation segment + * @param {Function} modelElement - Function to get model element + * @param {Function} propertiesOfStructuredType - Function to get properties + * @param {string} prefix - Navigation prefix + * @return {Array} Array of primitive property paths + */ +function primitivePaths(element, modelElement, propertiesOfStructuredType, prefix = '') { + const paths = []; + const elementType = modelElement(element.$Type); + if (!elementType) { + DEBUG?.(`Unknown type for element: ${JSON.stringify(element)}`); + return paths; + } + const propsOfType = propertiesOfStructuredType(elementType); + const ignore = Object.entries(propsOfType) + .filter(entry => entry[1].$Kind !== 'NavigationProperty') + .filter(entry => entry[1].$Type) + .filter(entry => nameParts(entry[1].$Type).qualifier !== 'Edm') + .filter(entry => !modelElement(entry[1].$Type)); + // Keep old logging + ignore.forEach(entry => DEBUG?.(`Unknown type for element: ${JSON.stringify(entry)}`)); + const properties = Object.entries(propsOfType) + .filter(entry => entry[1].$Kind !== 'NavigationProperty') + .filter(entry => !ignore.includes(entry)) + .map(entryToProperty({ path: prefix, typeRefChain: [] }, modelElement, propertiesOfStructuredType)); + for (let i = 0; i < properties.length; i++) { + const property = properties[i]; + if (!property.isComplex) { + paths.push(property.path); + continue; + } + const typeRefChainTail = property.typeRefChain[property.typeRefChain.length - 1]; + // Allow full cycle to be shown (0) times + if (property.typeRefChain.filter(_type => _type === typeRefChainTail).length > 1) { + DEBUG?.(`Cycle detected ${property.typeRefChain.join('->')}`); + continue; + } + const expanded = Object.entries(property.properties) + .filter(pProperty => pProperty[1].$Kind !== 'NavigationProperty') + .map(entryToProperty(property, modelElement, propertiesOfStructuredType)); + properties.splice(i + 1, 0, ...expanded); + } + return paths; +} +/** + * Helper function to convert entry to property + * @param {object} parent - Parent property + * @param {Function} modelElement - Function to get model element + * @param {Function} propertiesOfStructuredType - Function to get properties + * @return {Function} Function that converts entry to property + */ +function entryToProperty(parent, modelElement, propertiesOfStructuredType) { + return function (entry) { + const key = entry[0]; + const property = entry[1]; + const propertyType = property.$Type && modelElement(property.$Type); + if (propertyType && propertyType.$Kind && propertyType.$Kind === 'ComplexType') { + return { + properties: propertiesOfStructuredType(propertyType), + path: `${parent.path}${key}/`, + typeRefChain: parent.typeRefChain.concat(property.$Type), + isComplex: true + }; + } + return { + properties: {}, + path: `${parent.path}${key}`, + typeRefChain: [], + isComplex: false, + }; + }; +} +/** + * Build path parameters for key properties + * @param {object} keyNames - Key property names + * @param {object} properties - Properties of the type + * @param {string} level - Navigation level + * @param {object} options - Options object with keyAsSegment flag + * @return {Array} Array of parameter objects + */ +function buildKeyParameters(keyNames, properties, level, options = {}) { + const { keyAsSegment } = options; + const parameters = []; + keyNames.forEach(name => { + const property = properties[name]; + const param = { + name: name + '-' + level, + in: 'path', + required: true, + description: property[property.$Type === 'Edm.String' ? 'Core.Description' : '$Type'] + || `key: ${name}`, + schema: { + type: property.$Type === 'Edm.String' ? 'string' : + ['Edm.Int64', 'Edm.Int32', 'Edm.Int16', 'Edm.SByte', 'Edm.Byte'].includes(property.$Type) ? 'integer' : + 'string' + } + }; + // Add format for specific types + if (property.$Type === 'Edm.Int64') + param.schema.format = 'int64'; + if (property.$Type === 'Edm.Int32') + param.schema.format = 'int32'; + if (property.$Type === 'Edm.Guid') + param.schema.pattern = '^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$'; + parameters.push(param); + }); + return parameters; +} +/** + * Build path template with key parameters + * @param {string} prefix - Path prefix + * @param {Array} keyNames - Key property names + * @param {object} properties - Properties of the type + * @param {number} level - Navigation level + * @param {object} options - Options including keyAsSegment flag + * @return {string} Path template + */ +function buildPathWithKeys(prefix, keyNames, properties, level, options = {}) { + const { keyAsSegment } = options; + if (keyAsSegment) { + // Key as segment style: /path/keyValue + return keyNames.map(name => { + const property = properties[name]; + const valuePrefix = pathValuePrefix(property.$Type, keyAsSegment); + const valueSuffix = pathValueSuffix(property.$Type, keyAsSegment); + return `${prefix}/${valuePrefix}{${name}-${level}}${valueSuffix}`; + }).join(''); + } + else { + // Parentheses style: /path(key=value) + const keyParams = keyNames.map(name => { + const property = properties[name]; + const valuePrefix = pathValuePrefix(property.$Type, keyAsSegment); + const valueSuffix = pathValueSuffix(property.$Type, keyAsSegment); + return `${name}=${valuePrefix}{${name}-${level}}${valueSuffix}`; + }).join(','); + return `${prefix}(${keyParams})`; + } +} +module.exports = { + pathValuePrefix, + pathValueSuffix, + navigationPropertyPath, + propertyPath, + navigationPaths, + navigationPathMap, + primitivePaths, + entryToProperty, + buildKeyParameters, + buildPathWithKeys +}; +//# sourceMappingURL=paths.js.map \ No newline at end of file diff --git a/dist/lib/compile/modules/builders/paths.js.map b/dist/lib/compile/modules/builders/paths.js.map new file mode 100644 index 0000000..c7565bc --- /dev/null +++ b/dist/lib/compile/modules/builders/paths.js.map @@ -0,0 +1 @@ +{"version":3,"file":"paths.js","sourceRoot":"","sources":["../../../../../lib/compile/modules/builders/paths.js"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/lib/compile/modules/builders/responses.d.ts b/dist/lib/compile/modules/builders/responses.d.ts new file mode 100644 index 0000000..d3f099b --- /dev/null +++ b/dist/lib/compile/modules/builders/responses.d.ts @@ -0,0 +1,65 @@ +/** + * Build response object for collection + * @param {object} element - Model element + * @param {string} description - Response description + * @param {object} options - Options including csdlVersion + * @return {object} Response object + */ +export function collectionResponse(element: object, description: string, options?: object): object; +/** + * Build response object for single entity + * @param {object} element - Model element + * @param {string} description - Response description + * @return {object} Response object + */ +export function entityResponse(element: object, description: string): object; +/** + * Build response object for action/function result + * @param {object} returnType - Return type definition + * @param {string} description - Response description + * @param {Function} modelElement - Function to get model element + * @return {object} Response object + */ +export function operationResponse(returnType: object, description: string, modelElement: Function): object; +/** + * Build error response object + * @param {string} description - Error description + * @return {object} Error response object + */ +export function errorResponse(description: string): object; +/** + * Build response for $count endpoint + * @return {object} Count response object + */ +export function countResponse(): object; +/** + * Build response for batch endpoint + * @return {object} Batch response object + */ +export function batchResponse(): object; +/** + * Build standard OData responses + * @return {object} Standard responses object + */ +export function buildStandardResponses(): object; +/** + * Get schema for a type + * @param {string} typeName - Type name + * @param {Function} modelElement - Function to get model element + * @return {object} Schema object + */ +export function getTypeSchema(typeName: string, modelElement: Function): object; +/** + * Get OpenAPI schema for EDM type + * @param {string} typeName - EDM type name + * @return {object} Schema object + */ +export function getEdmTypeSchema(typeName: string): object; +/** + * Build response with ETag support + * @param {object} baseResponse - Base response object + * @param {boolean} required - Whether ETag is required + * @return {object} Response with ETag headers + */ +export function withETag(baseResponse: object, required?: boolean): object; +//# sourceMappingURL=responses.d.ts.map \ No newline at end of file diff --git a/dist/lib/compile/modules/builders/responses.d.ts.map b/dist/lib/compile/modules/builders/responses.d.ts.map new file mode 100644 index 0000000..6a1c44c --- /dev/null +++ b/dist/lib/compile/modules/builders/responses.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"responses.d.ts","sourceRoot":"","sources":["../../../../../lib/compile/modules/builders/responses.js"],"names":[],"mappings":"AAYA;;;;;;GAMG;AACH,4CALW,MAAM,eACN,MAAM,YACN,MAAM,GACL,MAAM,CA2BjB;AAED;;;;;GAKG;AACH,wCAJW,MAAM,eACN,MAAM,GACL,MAAM,CAajB;AAED;;;;;;GAMG;AACH,8CALW,MAAM,eACN,MAAM,2BAEL,MAAM,CAsCjB;AA0ED;;;;GAIG;AACH,2CAHW,MAAM,GACL,MAAM,CAajB;AAkBD;;;GAGG;AACH,iCAFY,MAAM,CAcjB;AAED;;;GAGG;AACH,iCAFY,MAAM,CAajB;AAjDD;;;GAGG;AACH,0CAFY,MAAM,CAYjB;AAxGD;;;;;GAKG;AACH,wCAJW,MAAM,2BAEL,MAAM,CAiBjB;AAED;;;;GAIG;AACH,2CAHW,MAAM,GACL,MAAM,CA4CjB;AAuED;;;;;GAKG;AACH,uCAJW,MAAM,aACN,OAAO,GACN,MAAM,CAkBjB"} \ No newline at end of file diff --git a/dist/lib/compile/modules/builders/responses.js b/dist/lib/compile/modules/builders/responses.js new file mode 100644 index 0000000..b688e4e --- /dev/null +++ b/dist/lib/compile/modules/builders/responses.js @@ -0,0 +1,266 @@ +"use strict"; +/** + * Response Building Module + * + * This module contains all functions related to building OpenAPI responses + * from CDS model elements. + */ +const { Logger } = require('../utils/logger'); +const logger = new Logger('csdl2openapi:responses'); +const DEBUG = logger.debug.bind(logger); +/** + * Build response object for collection + * @param {object} element - Model element + * @param {string} description - Response description + * @param {object} options - Options including csdlVersion + * @return {object} Response object + */ +function collectionResponse(element, description, options = {}) { + const { csdlVersion = '4.0' } = options; + return { + description: description || 'Retrieved entities', + content: { + 'application/json': { + schema: { + type: 'object', + title: 'Collection of ' + element.$Type, + properties: { + '@odata.count': { + $ref: '#/components/schemas/count' + }, + value: { + type: 'array', + items: { + $ref: '#/components/schemas/' + element.$Type.replace(/\./g, '_') + } + } + } + } + } + } + }; +} +/** + * Build response object for single entity + * @param {object} element - Model element + * @param {string} description - Response description + * @return {object} Response object + */ +function entityResponse(element, description) { + return { + description: description || 'Retrieved entity', + content: { + 'application/json': { + schema: { + $ref: '#/components/schemas/' + element.$Type.replace(/\./g, '_') + } + } + } + }; +} +/** + * Build response object for action/function result + * @param {object} returnType - Return type definition + * @param {string} description - Response description + * @param {Function} modelElement - Function to get model element + * @return {object} Response object + */ +function operationResponse(returnType, description, modelElement) { + if (!returnType || !returnType.$Type) { + return { + description: description || 'Success', + content: {} + }; + } + const response = { + description: description || 'Success', + content: { + 'application/json': { + schema: {} + } + } + }; + const schema = response.content['application/json'].schema; + if (returnType.$Collection) { + schema.type = 'object'; + schema.title = `Collection of ${returnType.$Type}`; + schema.properties = { + '@odata.count': { + $ref: '#/components/schemas/count' + }, + value: { + type: 'array', + items: getTypeSchema(returnType.$Type, modelElement) + } + }; + } + else { + Object.assign(schema, getTypeSchema(returnType.$Type, modelElement)); + } + return response; +} +/** + * Get schema for a type + * @param {string} typeName - Type name + * @param {Function} modelElement - Function to get model element + * @return {object} Schema object + */ +function getTypeSchema(typeName, modelElement) { + // Check if it's an Edm type + if (typeName.startsWith('Edm.')) { + return getEdmTypeSchema(typeName); + } + // Check if it's a model type + const type = modelElement(typeName); + if (type) { + return { $ref: '#/components/schemas/' + typeName.replace(/\./g, '_') }; + } + // Default to string + DEBUG?.(`Unknown type: ${typeName}, defaulting to string`); + return { type: 'string' }; +} +/** + * Get OpenAPI schema for EDM type + * @param {string} typeName - EDM type name + * @return {object} Schema object + */ +function getEdmTypeSchema(typeName) { + const edmTypeMap = { + 'Edm.Binary': { type: 'string', format: 'base64' }, + 'Edm.Boolean': { type: 'boolean' }, + 'Edm.Byte': { type: 'integer', format: 'uint8' }, + 'Edm.Date': { type: 'string', format: 'date' }, + 'Edm.DateTimeOffset': { type: 'string', format: 'date-time' }, + 'Edm.Decimal': { type: 'number', format: 'decimal' }, + 'Edm.Double': { type: 'number', format: 'double' }, + 'Edm.Duration': { type: 'string', format: 'duration' }, + 'Edm.Guid': { + type: 'string', + format: 'uuid', + pattern: '^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$' + }, + 'Edm.Int16': { type: 'integer', format: 'int16' }, + 'Edm.Int32': { type: 'integer', format: 'int32' }, + 'Edm.Int64': { type: 'integer', format: 'int64' }, + 'Edm.SByte': { type: 'integer', format: 'int8' }, + 'Edm.Single': { type: 'number', format: 'float' }, + 'Edm.String': { type: 'string' }, + 'Edm.TimeOfDay': { type: 'string', format: 'time' }, + 'Edm.Geography': { type: 'object' }, + 'Edm.GeographyPoint': { type: 'object' }, + 'Edm.GeographyLineString': { type: 'object' }, + 'Edm.GeographyPolygon': { type: 'object' }, + 'Edm.GeographyMultiPoint': { type: 'object' }, + 'Edm.GeographyMultiLineString': { type: 'object' }, + 'Edm.GeographyMultiPolygon': { type: 'object' }, + 'Edm.GeographyCollection': { type: 'object' }, + 'Edm.Geometry': { type: 'object' }, + 'Edm.GeometryPoint': { type: 'object' }, + 'Edm.GeometryLineString': { type: 'object' }, + 'Edm.GeometryPolygon': { type: 'object' }, + 'Edm.GeometryMultiPoint': { type: 'object' }, + 'Edm.GeometryMultiLineString': { type: 'object' }, + 'Edm.GeometryMultiPolygon': { type: 'object' }, + 'Edm.GeometryCollection': { type: 'object' }, + 'Edm.Stream': { type: 'string', format: 'binary' } + }; + return edmTypeMap[typeName] || { type: 'string' }; +} +/** + * Build error response object + * @param {string} description - Error description + * @return {object} Error response object + */ +function errorResponse(description) { + return { + description: description || 'Error', + content: { + 'application/json': { + schema: { + $ref: '#/components/schemas/error' + } + } + } + }; +} +/** + * Build standard OData responses + * @return {object} Standard responses object + */ +function buildStandardResponses() { + return { + error: errorResponse('Error'), + '400': errorResponse('Bad Request'), + '401': errorResponse('Unauthorized'), + '403': errorResponse('Forbidden'), + '404': errorResponse('Not Found'), + '500': errorResponse('Internal Server Error'), + '501': errorResponse('Not Implemented') + }; +} +/** + * Build response for $count endpoint + * @return {object} Count response object + */ +function countResponse() { + return { + description: 'The count of the resource', + content: { + 'text/plain': { + schema: { + type: 'integer', + minimum: 0 + } + } + } + }; +} +/** + * Build response for batch endpoint + * @return {object} Batch response object + */ +function batchResponse() { + return { + description: 'Batch response', + content: { + 'multipart/mixed': { + schema: { + type: 'string' + } + } + } + }; +} +/** + * Build response with ETag support + * @param {object} baseResponse - Base response object + * @param {boolean} required - Whether ETag is required + * @return {object} Response with ETag headers + */ +function withETag(baseResponse, required = false) { + const response = JSON.parse(JSON.stringify(baseResponse)); // Deep clone + response.headers = response.headers || {}; + response.headers.ETag = { + description: 'Entity tag', + schema: { + type: 'string' + } + }; + if (required) { + response.headers.ETag.required = true; + } + return response; +} +module.exports = { + collectionResponse, + entityResponse, + operationResponse, + errorResponse, + countResponse, + batchResponse, + buildStandardResponses, + getTypeSchema, + getEdmTypeSchema, + withETag +}; +//# sourceMappingURL=responses.js.map \ No newline at end of file diff --git a/dist/lib/compile/modules/builders/responses.js.map b/dist/lib/compile/modules/builders/responses.js.map new file mode 100644 index 0000000..d2ec8ee --- /dev/null +++ b/dist/lib/compile/modules/builders/responses.js.map @@ -0,0 +1 @@ +{"version":3,"file":"responses.js","sourceRoot":"","sources":["../../../../../lib/compile/modules/builders/responses.js"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/lib/compile/modules/utils/naming.d.ts b/dist/lib/compile/modules/utils/naming.d.ts index 5123c7a..9052f46 100644 --- a/dist/lib/compile/modules/utils/naming.d.ts +++ b/dist/lib/compile/modules/utils/naming.d.ts @@ -26,4 +26,10 @@ export function splitName(name: string): string; * @return {string} namespace-qualified name */ export function namespaceQualifiedName(qualifiedName: string, namespace: object): string; +/** + * Unpack EnumMember value if it uses CSDL JSON CS01 style + * @param {string|object} member Enum member value + * @return {string} Unpacked enum member + */ +export function enumMember(member: string | object): string; //# sourceMappingURL=naming.d.ts.map \ No newline at end of file diff --git a/dist/lib/compile/modules/utils/naming.d.ts.map b/dist/lib/compile/modules/utils/naming.d.ts.map index 6f66b9a..11dda56 100644 --- a/dist/lib/compile/modules/utils/naming.d.ts.map +++ b/dist/lib/compile/modules/utils/naming.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"naming.d.ts","sourceRoot":"","sources":["../../../../../lib/compile/modules/utils/naming.js"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;;GAIG;AACH,yCAHW,MAAM,GACL,MAAM,CASjB;AAED;;;;GAIG;AACH,mCAHW,MAAM,GACL,OAAO,CAIlB;AAED;;;;GAIG;AACH,gCAHW,MAAM,GACL,MAAM,CAIjB;AAED;;;;;GAKG;AACH,sDAJW,MAAM,aACN,MAAM,GACL,MAAM,CAKjB"} \ No newline at end of file +{"version":3,"file":"naming.d.ts","sourceRoot":"","sources":["../../../../../lib/compile/modules/utils/naming.js"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;;GAIG;AACH,yCAHW,MAAM,GACL,MAAM,CASjB;AAED;;;;GAIG;AACH,mCAHW,MAAM,GACL,OAAO,CAIlB;AAED;;;;GAIG;AACH,gCAHW,MAAM,GACL,MAAM,CAIjB;AAED;;;;;GAKG;AACH,sDAJW,MAAM,aACN,MAAM,GACL,MAAM,CAKjB;AAED;;;;GAIG;AACH,mCAHW,MAAM,GAAC,MAAM,GACZ,MAAM,CAOjB"} \ No newline at end of file diff --git a/dist/lib/compile/modules/utils/naming.js b/dist/lib/compile/modules/utils/naming.js index ce7eeac..35c5972 100644 --- a/dist/lib/compile/modules/utils/naming.js +++ b/dist/lib/compile/modules/utils/naming.js @@ -41,10 +41,22 @@ function namespaceQualifiedName(qualifiedName, namespace) { let np = nameParts(qualifiedName); return namespace[np.qualifier] + '.' + np.name; } +/** + * Unpack EnumMember value if it uses CSDL JSON CS01 style + * @param {string|object} member Enum member value + * @return {string} Unpacked enum member + */ +function enumMember(member) { + if (typeof member == 'string') + return member; + else if (typeof member == 'object') + return member.$EnumMember; +} module.exports = { nameParts, isIdentifier, splitName, - namespaceQualifiedName + namespaceQualifiedName, + enumMember }; //# sourceMappingURL=naming.js.map \ No newline at end of file diff --git a/dist/lib/compile/modules/utils/naming.js.map b/dist/lib/compile/modules/utils/naming.js.map index 00f270b..000ca40 100644 --- a/dist/lib/compile/modules/utils/naming.js.map +++ b/dist/lib/compile/modules/utils/naming.js.map @@ -1 +1 @@ -{"version":3,"file":"naming.js","sourceRoot":"","sources":["../../../../../lib/compile/modules/utils/naming.js"],"names":[],"mappings":";AAAA;;GAEG;AAEH;;;;GAIG;AACH,SAAS,SAAS,CAAC,aAAa;IAC5B,MAAM,GAAG,GAAG,aAAa,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IAC3C,OAAO,CAAC,MAAM,CAAC,GAAG,GAAG,CAAC,EAAE,yBAAyB,GAAG,aAAa,CAAC,CAAC;IACnE,OAAO;QACH,SAAS,EAAE,aAAa,CAAC,SAAS,CAAC,CAAC,EAAE,GAAG,CAAC;QAC1C,IAAI,EAAE,aAAa,CAAC,SAAS,CAAC,GAAG,GAAG,CAAC,CAAC;KACzC,CAAC;AACN,CAAC;AAED;;;;GAIG;AACH,SAAS,YAAY,CAAC,IAAI;IACtB,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;AACxD,CAAC;AAED;;;;GAIG;AACH,SAAS,SAAS,CAAC,IAAI;IACnB,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;AACpF,CAAC;AAED;;;;;GAKG;AACH,SAAS,sBAAsB,CAAC,aAAa,EAAE,SAAS;IACpD,IAAI,EAAE,GAAG,SAAS,CAAC,aAAa,CAAC,CAAC;IAClC,OAAO,SAAS,CAAC,EAAE,CAAC,SAAS,CAAC,GAAG,GAAG,GAAG,EAAE,CAAC,IAAI,CAAC;AACnD,CAAC;AAED,MAAM,CAAC,OAAO,GAAG;IACb,SAAS;IACT,YAAY;IACZ,SAAS;IACT,sBAAsB;CACzB,CAAC"} \ No newline at end of file +{"version":3,"file":"naming.js","sourceRoot":"","sources":["../../../../../lib/compile/modules/utils/naming.js"],"names":[],"mappings":";AAAA;;GAEG;AAEH;;;;GAIG;AACH,SAAS,SAAS,CAAC,aAAa;IAC5B,MAAM,GAAG,GAAG,aAAa,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IAC3C,OAAO,CAAC,MAAM,CAAC,GAAG,GAAG,CAAC,EAAE,yBAAyB,GAAG,aAAa,CAAC,CAAC;IACnE,OAAO;QACH,SAAS,EAAE,aAAa,CAAC,SAAS,CAAC,CAAC,EAAE,GAAG,CAAC;QAC1C,IAAI,EAAE,aAAa,CAAC,SAAS,CAAC,GAAG,GAAG,CAAC,CAAC;KACzC,CAAC;AACN,CAAC;AAED;;;;GAIG;AACH,SAAS,YAAY,CAAC,IAAI;IACtB,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;AACxD,CAAC;AAED;;;;GAIG;AACH,SAAS,SAAS,CAAC,IAAI;IACnB,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;AACpF,CAAC;AAED;;;;;GAKG;AACH,SAAS,sBAAsB,CAAC,aAAa,EAAE,SAAS;IACpD,IAAI,EAAE,GAAG,SAAS,CAAC,aAAa,CAAC,CAAC;IAClC,OAAO,SAAS,CAAC,EAAE,CAAC,SAAS,CAAC,GAAG,GAAG,GAAG,EAAE,CAAC,IAAI,CAAC;AACnD,CAAC;AAED;;;;GAIG;AACH,SAAS,UAAU,CAAC,MAAM;IACtB,IAAI,OAAO,MAAM,IAAI,QAAQ;QACzB,OAAO,MAAM,CAAC;SACb,IAAI,OAAO,MAAM,IAAI,QAAQ;QAC9B,OAAO,MAAM,CAAC,WAAW,CAAC;AAClC,CAAC;AAED,MAAM,CAAC,OAAO,GAAG;IACb,SAAS;IACT,YAAY;IACZ,SAAS;IACT,sBAAsB;IACtB,UAAU;CACb,CAAC"} \ No newline at end of file