From 4c6b6e9abbb2eb89bc40286bc8a50abd5279b54b Mon Sep 17 00:00:00 2001 From: Ralf Handl Date: Tue, 3 Mar 2020 09:49:11 +0100 Subject: [PATCH] Deep-update support on container level (#68) * Deep-update support on container level * Deep update means "create" for related entities --- lib/csdl2openapi.js | 5 ++- package.json | 2 +- test/csdl2openapi.test.js | 76 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 81 insertions(+), 2 deletions(-) diff --git a/lib/csdl2openapi.js b/lib/csdl2openapi.js index 377cffcb..7b0cf6a6 100644 --- a/lib/csdl2openapi.js +++ b/lib/csdl2openapi.js @@ -52,6 +52,7 @@ module.exports.csdl2openapi = function ( const entityContainer = csdl.$EntityContainer ? modelElement(csdl.$EntityContainer) : {}; const keyAsSegment = entityContainer[voc.Capabilities.KeyAsSegmentSupported]; + const deepUpdate = entityContainer[voc.Capabilities.DeepUpdateSupport] && entityContainer[voc.Capabilities.DeepUpdateSupport].Supported; const openapi = { openapi: '3.0.2', @@ -174,7 +175,7 @@ module.exports.csdl2openapi = function ( function vocabularies(voc, alias) { const terms = { Authorization: ['Authorizations', 'SecuritySchemes'], - Capabilities: ['BatchSupported', 'ChangeTracking', 'CountRestrictions', 'DeleteRestrictions', 'ExpandRestrictions', + Capabilities: ['BatchSupported', 'ChangeTracking', 'CountRestrictions', 'DeleteRestrictions', 'DeepUpdateSupport', 'ExpandRestrictions', 'FilterRestrictions', 'IndexableByKey', 'InsertRestrictions', 'KeyAsSegmentSupported', 'NavigationRestrictions', 'SearchRestrictions', 'SelectSupport', 'SkipSupported', 'SortRestrictions', 'ReadRestrictions', 'TopSupported', 'UpdateRestrictions'], @@ -1481,6 +1482,8 @@ module.exports.csdl2openapi = function ( allProperties[name] = schema(property); if (property.$Kind == 'NavigationProperty') { creProperties[name] = schema(property, '-create'); + if (deepUpdate) + updProperties[name] = schema(property, '-create'); } else { if (property[voc.Core.Permissions] == 'Read' || property[voc.Core.Computed]) { let index = required.indexOf(name); diff --git a/package.json b/package.json index 01c26eea..b384aedf 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "odata-openapi", - "version": "0.4.1", + "version": "0.5.0", "description": "Convert OData CSDL XML or CSDL JSON to OpenAPI", "homepage": "https://github.com/oasis-tcs/odata-openapi/blob/master/lib/README.md", "bugs": "https://github.com/oasis-tcs/odata-openapi/issues", diff --git a/test/csdl2openapi.test.js b/test/csdl2openapi.test.js index 3e42f031..8d683ddd 100644 --- a/test/csdl2openapi.test.js +++ b/test/csdl2openapi.test.js @@ -1449,6 +1449,82 @@ describe('Edge cases', function () { assert.deepStrictEqual(actual.paths['/roots/act'].post, expected.paths['/roots/act'].post, 'POST /roots/act'); }) + it('Deep update on container level', function () { + const csdl = { + $Reference: { dummy: { "$Include": [{ "$Namespace": "Org.OData.Capabilities.V1", "$Alias": "Capabilities" }] } }, + $EntityContainer: 'this.Container', + this: { + root: { + $Kind: 'EntityType', $Key: ['key'], + key: {}, + one: {}, + two: {}, + children: { $Type: 'this.child', $Kind: 'NavigationProperty', $ContainsTarget: true, $Collection: true }, + }, + child: { + $Kind: 'EntityType', $Key: ['key'], + key: {}, + one: {}, + two: {}, + nav: { $Type: 'this.grandchild', $Kind: 'NavigationProperty', $ContainsTarget: true }, + }, + grandchild: { + $Kind: 'EntityType', $Key: ['key'], + key: {}, + one: {}, + two: {} + }, + Container: { + '@Capabilities.KeyAsSegmentSupported': true, + '@Capabilities.DeepUpdateSupport': { Supported: true }, + roots: { + $Type: 'this.root', $Collection: true + } + } + } + }; + + const expected = { + paths: { + "/$batch": { post: {} }, + "/roots": { get: {}, post: {} }, + "/roots/{key}": { get: {}, patch: {}, delete: {} }, + "/roots/{key}/children": { get: {}, post: {} }, + "/roots/{key}/children/{key-1}": { get: {}, patch: {}, delete: {} }, + "/roots/{key}/children/{key-1}/nav": { get: {}, patch: {} }, + }, + components: { + schemas: { + 'this.root-update': { + type: 'object', + title: 'root (for update)', + properties: { + one: { type: 'string' }, two: { type: 'string' }, + children: { type: 'array', items: { $ref: '#/components/schemas/this.child-create' } } + } + }, + 'this.child-update': { + type: 'object', + title: 'child (for update)', + properties: { + one: { type: 'string' }, two: { type: 'string' }, + nav: { $ref: '#/components/schemas/this.grandchild-create' } + } + } + } + } + } + + const actual = lib.csdl2openapi(csdl, {}); + + assert.deepStrictEqual(paths(actual), paths(expected), 'Paths'); + assert.deepStrictEqual(operations(actual), operations(expected), 'Operations'); + + //TODO: check components + assert.deepStrictEqual(actual.components.schemas['this.root-update'], expected.components.schemas['this.root-update'], 'root update structure') + assert.deepStrictEqual(actual.components.schemas['this.child-update'], expected.components.schemas['this.child-update'], 'child update structure') + }) + }) function check(actual, expected) {