diff --git a/CHANGELOG.md b/CHANGELOG.md index 7c0a768..b89e7ca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/). - Added `defaultProtocol` configuration option as fallback if no config is provided. ### Changed - set `odata` as the service protocol if no protocol is set to match the default behavior of `@sap/cds`. Provide `cds.env.openapi.defaultProtocol = "rest"` to restore old behavior. +- ER diagrams are now rendered using the yuml.me v1 API (`app.yuml.me`), avoiding the 'please migrate' image. The diagram and legend are displayed as clickable SVG images. ### Deprecated ### Removed ### Fixed diff --git a/lib/compile/diagram.js b/lib/compile/diagram.js index 0b8ce3a..e9e0c7b 100644 --- a/lib/compile/diagram.js +++ b/lib/compile/diagram.js @@ -59,25 +59,28 @@ class Diagram { Object.keys(entityContainer).filter(name => isIdentifier(name)).reverse().forEach(name => { const resource = entityContainer[name]; if (resource.$Type) { - diagram += `${this.#comma}[${name}%20${this.#color.resource}]` // additional space in case entity set and type have same name + diagram += `${this.#comma}[${name}\u200C${this.#color.resource}]` // U+200C (ZWNJ) disambiguates entity set node from same-named entity type node + `++-${cardinality(resource)}>[${nameParts(resource.$Type).name}]`; } else if (resource.$Action) { - diagram += `${this.#comma}[${name}${this.#color.resource}]`; - const overload = this.#meta.modelElement(resource.$Action).find(pOverload => !pOverload.$IsBound); - diagram += this.#overloadDiagram(name, overload); - } else if (resource.$Function) { - diagram += `${this.#comma}[${name}${this.#color.resource}]`; - const overloads = this.#meta.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 += this.#overloadDiagram(name, unbound[0]); - } + diagram += `${this.#comma}[${name}${this.#color.resource}]`; + const overload = this.#meta.modelElement(resource.$Action).find(pOverload => !pOverload.$IsBound); + diagram += this.#overloadDiagram(name, overload); + } else if (resource.$Function) { + diagram += `${this.#comma}[${name}${this.#color.resource}]`; + const overloads = this.#meta.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 += this.#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${this.#color.external}],[ComplexType${this.#color.complexType}],[EntityType${this.#color.entityType}],[EntitySet/Singleton/Operation${this.#color.resource}])`; + const legendDsl = `@direction LR\n[External.Type${this.#color.external}]-[ComplexType${this.#color.complexType}]-[EntityType${this.#color.entityType}]-[EntitySet/Singleton/Operation${this.#color.resource}]`; + const erUrl = `https://app.yuml.me/diagram/v1/class/plain/${encodeURIComponent(diagram)}.svg`; + const legendUrl = `https://app.yuml.me/diagram/v1/class/plain/${encodeURIComponent(legendDsl)}.svg`; + diagram = `\n\n### Entity Data Model\n[![ER Diagram](${erUrl})](${erUrl})\n\n#### Legend\n`; } return diagram; diff --git a/test/lib/compile/csdl2openapi.test.js b/test/lib/compile/csdl2openapi.test.js index e50aec8..2f516e3 100644 --- a/test/lib/compile/csdl2openapi.test.js +++ b/test/lib/compile/csdl2openapi.test.js @@ -2404,11 +2404,11 @@ see [Expand](http://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part1-prot [ "Use the Core.LongDescription or Core.Description annotation on your CDS service to provide a meaningful description.", "", - "## Entity Data Model", - "![ER Diagram](https://yuml.me/diagram/class/[root{bg:lightslategray}],[root]->[other],[other{bg:lightslategray}],[act{bg:lawngreen}]->[root],[act{bg:lawngreen}]in->[root],[others%20{bg:lawngreen}]++-*>[other],[roots%20{bg:lawngreen}]++-*>[root])", + "### Entity Data Model", + "[![ER Diagram](https://app.yuml.me/diagram/v1/class/plain/%5Broot%7Bbg%3Alightslategray%7D%5D%2C%5Broot%5D-%3E%5Bother%5D%2C%5Bother%7Bbg%3Alightslategray%7D%5D%2C%5Bact%7Bbg%3Alawngreen%7D%5D-%3E%5Broot%5D%2C%5Bact%7Bbg%3Alawngreen%7D%5Din-%3E%5Broot%5D%2C%5Bothers%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5Bother%5D%2C%5Broots%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5Broot%5D.svg)](https://app.yuml.me/diagram/v1/class/plain/%5Broot%7Bbg%3Alightslategray%7D%5D%2C%5Broot%5D-%3E%5Bother%5D%2C%5Bother%7Bbg%3Alightslategray%7D%5D%2C%5Bact%7Bbg%3Alawngreen%7D%5D-%3E%5Broot%5D%2C%5Bact%7Bbg%3Alawngreen%7D%5Din-%3E%5Broot%5D%2C%5Bothers%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5Bother%5D%2C%5Broots%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5Broot%5D.svg)", "", - "### Legend", - "![Legend](https://yuml.me/diagram/plain;dir:TB;scale:60/class/[External.Type{bg:whitesmoke}],[ComplexType],[EntityType{bg:lightslategray}],[EntitySet/Singleton/Operation{bg:lawngreen}])", + "#### Legend", + "", ], "diagram" ); diff --git a/test/lib/compile/data/Northwind-key-as-segment.openapi3.json b/test/lib/compile/data/Northwind-key-as-segment.openapi3.json index d70f87d..6949dae 100644 --- a/test/lib/compile/data/Northwind-key-as-segment.openapi3.json +++ b/test/lib/compile/data/Northwind-key-as-segment.openapi3.json @@ -2,7 +2,7 @@ "openapi": "3.0.2", "info": { "title": "Use the title annotation on your CDS service to provide a meaningful title.", - "description": "Use the Core.LongDescription or Core.Description annotation on your CDS service to provide a meaningful description.\n\n## Entity Data Model\n![ER Diagram](https://yuml.me/diagram/class/[Category{bg:lightslategray}],[CustomerDemographic{bg:lightslategray}],[Customer{bg:lightslategray}],[Customer]*-*[CustomerDemographic],[Employee{bg:lightslategray}],[Employee]*-0..1[Employee],[Order_Detail{bg:lightslategray}],[Order_Detail]*-[Order],[Order{bg:lightslategray}],[Order]*-0..1[Customer],[Order]*-0..1[Employee],[Product{bg:lightslategray}],[Product]*-0..1[Category],[Product]-*[Order_Detail],[Region{bg:lightslategray}],[Shipper{bg:lightslategray}],[Shipper]0..1-*[Order],[Supplier{bg:lightslategray}],[Supplier]0..1-*[Product],[Territory{bg:lightslategray}],[Territory]*-[Region],[Territory]*-*[Employee],[Alphabetical_list_of_product{bg:lightslategray}],[Category_Sales_for_1997{bg:lightslategray}],[Current_Product_List{bg:lightslategray}],[Customer_and_Suppliers_by_City{bg:lightslategray}],[Invoice{bg:lightslategray}],[Order_Details_Extended{bg:lightslategray}],[Order_Subtotal{bg:lightslategray}],[Orders_Qry{bg:lightslategray}],[Product_Sales_for_1997{bg:lightslategray}],[Products_Above_Average_Price{bg:lightslategray}],[Products_by_Category{bg:lightslategray}],[Sales_by_Category{bg:lightslategray}],[Sales_Totals_by_Amount{bg:lightslategray}],[Summary_of_Sales_by_Quarter{bg:lightslategray}],[Summary_of_Sales_by_Year{bg:lightslategray}],[Summary_of_Sales_by_Years%20{bg:lawngreen}]++-*>[Summary_of_Sales_by_Year],[Summary_of_Sales_by_Quarters%20{bg:lawngreen}]++-*>[Summary_of_Sales_by_Quarter],[Sales_Totals_by_Amounts%20{bg:lawngreen}]++-*>[Sales_Totals_by_Amount],[Sales_by_Categories%20{bg:lawngreen}]++-*>[Sales_by_Category],[Products_by_Categories%20{bg:lawngreen}]++-*>[Products_by_Category],[Products_Above_Average_Prices%20{bg:lawngreen}]++-*>[Products_Above_Average_Price],[Product_Sales_for_1997%20{bg:lawngreen}]++-*>[Product_Sales_for_1997],[Orders_Qries%20{bg:lawngreen}]++-*>[Orders_Qry],[Order_Subtotals%20{bg:lawngreen}]++-*>[Order_Subtotal],[Order_Details_Extendeds%20{bg:lawngreen}]++-*>[Order_Details_Extended],[Invoices%20{bg:lawngreen}]++-*>[Invoice],[Customer_and_Suppliers_by_Cities%20{bg:lawngreen}]++-*>[Customer_and_Suppliers_by_City],[Current_Product_Lists%20{bg:lawngreen}]++-*>[Current_Product_List],[Category_Sales_for_1997%20{bg:lawngreen}]++-*>[Category_Sales_for_1997],[Alphabetical_list_of_products%20{bg:lawngreen}]++-*>[Alphabetical_list_of_product],[Territories%20{bg:lawngreen}]++-*>[Territory],[Suppliers%20{bg:lawngreen}]++-*>[Supplier],[Shippers%20{bg:lawngreen}]++-*>[Shipper],[Regions%20{bg:lawngreen}]++-*>[Region],[Products%20{bg:lawngreen}]++-*>[Product],[Orders%20{bg:lawngreen}]++-*>[Order],[Order_Details%20{bg:lawngreen}]++-*>[Order_Detail],[Employees%20{bg:lawngreen}]++-*>[Employee],[Customers%20{bg:lawngreen}]++-*>[Customer],[CustomerDemographics%20{bg:lawngreen}]++-*>[CustomerDemographic],[Categories%20{bg:lawngreen}]++-*>[Category])\n\n### Legend\n![Legend](https://yuml.me/diagram/plain;dir:TB;scale:60/class/[External.Type{bg:whitesmoke}],[ComplexType],[EntityType{bg:lightslategray}],[EntitySet/Singleton/Operation{bg:lawngreen}])", + "description": "Use the Core.LongDescription or Core.Description annotation on your CDS service to provide a meaningful description.\n\n### Entity Data Model\n[![ER Diagram](https://app.yuml.me/diagram/v1/class/plain/%5BCategory%7Bbg%3Alightslategray%7D%5D%2C%5BCustomerDemographic%7Bbg%3Alightslategray%7D%5D%2C%5BCustomer%7Bbg%3Alightslategray%7D%5D%2C%5BCustomer%5D*-*%5BCustomerDemographic%5D%2C%5BEmployee%7Bbg%3Alightslategray%7D%5D%2C%5BEmployee%5D*-0..1%5BEmployee%5D%2C%5BOrder_Detail%7Bbg%3Alightslategray%7D%5D%2C%5BOrder_Detail%5D*-%5BOrder%5D%2C%5BOrder%7Bbg%3Alightslategray%7D%5D%2C%5BOrder%5D*-0..1%5BCustomer%5D%2C%5BOrder%5D*-0..1%5BEmployee%5D%2C%5BProduct%7Bbg%3Alightslategray%7D%5D%2C%5BProduct%5D*-0..1%5BCategory%5D%2C%5BProduct%5D-*%5BOrder_Detail%5D%2C%5BRegion%7Bbg%3Alightslategray%7D%5D%2C%5BShipper%7Bbg%3Alightslategray%7D%5D%2C%5BShipper%5D0..1-*%5BOrder%5D%2C%5BSupplier%7Bbg%3Alightslategray%7D%5D%2C%5BSupplier%5D0..1-*%5BProduct%5D%2C%5BTerritory%7Bbg%3Alightslategray%7D%5D%2C%5BTerritory%5D*-%5BRegion%5D%2C%5BTerritory%5D*-*%5BEmployee%5D%2C%5BAlphabetical_list_of_product%7Bbg%3Alightslategray%7D%5D%2C%5BCategory_Sales_for_1997%7Bbg%3Alightslategray%7D%5D%2C%5BCurrent_Product_List%7Bbg%3Alightslategray%7D%5D%2C%5BCustomer_and_Suppliers_by_City%7Bbg%3Alightslategray%7D%5D%2C%5BInvoice%7Bbg%3Alightslategray%7D%5D%2C%5BOrder_Details_Extended%7Bbg%3Alightslategray%7D%5D%2C%5BOrder_Subtotal%7Bbg%3Alightslategray%7D%5D%2C%5BOrders_Qry%7Bbg%3Alightslategray%7D%5D%2C%5BProduct_Sales_for_1997%7Bbg%3Alightslategray%7D%5D%2C%5BProducts_Above_Average_Price%7Bbg%3Alightslategray%7D%5D%2C%5BProducts_by_Category%7Bbg%3Alightslategray%7D%5D%2C%5BSales_by_Category%7Bbg%3Alightslategray%7D%5D%2C%5BSales_Totals_by_Amount%7Bbg%3Alightslategray%7D%5D%2C%5BSummary_of_Sales_by_Quarter%7Bbg%3Alightslategray%7D%5D%2C%5BSummary_of_Sales_by_Year%7Bbg%3Alightslategray%7D%5D%2C%5BSummary_of_Sales_by_Years%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BSummary_of_Sales_by_Year%5D%2C%5BSummary_of_Sales_by_Quarters%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BSummary_of_Sales_by_Quarter%5D%2C%5BSales_Totals_by_Amounts%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BSales_Totals_by_Amount%5D%2C%5BSales_by_Categories%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BSales_by_Category%5D%2C%5BProducts_by_Categories%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BProducts_by_Category%5D%2C%5BProducts_Above_Average_Prices%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BProducts_Above_Average_Price%5D%2C%5BProduct_Sales_for_1997%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BProduct_Sales_for_1997%5D%2C%5BOrders_Qries%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BOrders_Qry%5D%2C%5BOrder_Subtotals%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BOrder_Subtotal%5D%2C%5BOrder_Details_Extendeds%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BOrder_Details_Extended%5D%2C%5BInvoices%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BInvoice%5D%2C%5BCustomer_and_Suppliers_by_Cities%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BCustomer_and_Suppliers_by_City%5D%2C%5BCurrent_Product_Lists%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BCurrent_Product_List%5D%2C%5BCategory_Sales_for_1997%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BCategory_Sales_for_1997%5D%2C%5BAlphabetical_list_of_products%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BAlphabetical_list_of_product%5D%2C%5BTerritories%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BTerritory%5D%2C%5BSuppliers%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BSupplier%5D%2C%5BShippers%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BShipper%5D%2C%5BRegions%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BRegion%5D%2C%5BProducts%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BProduct%5D%2C%5BOrders%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BOrder%5D%2C%5BOrder_Details%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BOrder_Detail%5D%2C%5BEmployees%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BEmployee%5D%2C%5BCustomers%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BCustomer%5D%2C%5BCustomerDemographics%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BCustomerDemographic%5D%2C%5BCategories%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BCategory%5D.svg)](https://app.yuml.me/diagram/v1/class/plain/%5BCategory%7Bbg%3Alightslategray%7D%5D%2C%5BCustomerDemographic%7Bbg%3Alightslategray%7D%5D%2C%5BCustomer%7Bbg%3Alightslategray%7D%5D%2C%5BCustomer%5D*-*%5BCustomerDemographic%5D%2C%5BEmployee%7Bbg%3Alightslategray%7D%5D%2C%5BEmployee%5D*-0..1%5BEmployee%5D%2C%5BOrder_Detail%7Bbg%3Alightslategray%7D%5D%2C%5BOrder_Detail%5D*-%5BOrder%5D%2C%5BOrder%7Bbg%3Alightslategray%7D%5D%2C%5BOrder%5D*-0..1%5BCustomer%5D%2C%5BOrder%5D*-0..1%5BEmployee%5D%2C%5BProduct%7Bbg%3Alightslategray%7D%5D%2C%5BProduct%5D*-0..1%5BCategory%5D%2C%5BProduct%5D-*%5BOrder_Detail%5D%2C%5BRegion%7Bbg%3Alightslategray%7D%5D%2C%5BShipper%7Bbg%3Alightslategray%7D%5D%2C%5BShipper%5D0..1-*%5BOrder%5D%2C%5BSupplier%7Bbg%3Alightslategray%7D%5D%2C%5BSupplier%5D0..1-*%5BProduct%5D%2C%5BTerritory%7Bbg%3Alightslategray%7D%5D%2C%5BTerritory%5D*-%5BRegion%5D%2C%5BTerritory%5D*-*%5BEmployee%5D%2C%5BAlphabetical_list_of_product%7Bbg%3Alightslategray%7D%5D%2C%5BCategory_Sales_for_1997%7Bbg%3Alightslategray%7D%5D%2C%5BCurrent_Product_List%7Bbg%3Alightslategray%7D%5D%2C%5BCustomer_and_Suppliers_by_City%7Bbg%3Alightslategray%7D%5D%2C%5BInvoice%7Bbg%3Alightslategray%7D%5D%2C%5BOrder_Details_Extended%7Bbg%3Alightslategray%7D%5D%2C%5BOrder_Subtotal%7Bbg%3Alightslategray%7D%5D%2C%5BOrders_Qry%7Bbg%3Alightslategray%7D%5D%2C%5BProduct_Sales_for_1997%7Bbg%3Alightslategray%7D%5D%2C%5BProducts_Above_Average_Price%7Bbg%3Alightslategray%7D%5D%2C%5BProducts_by_Category%7Bbg%3Alightslategray%7D%5D%2C%5BSales_by_Category%7Bbg%3Alightslategray%7D%5D%2C%5BSales_Totals_by_Amount%7Bbg%3Alightslategray%7D%5D%2C%5BSummary_of_Sales_by_Quarter%7Bbg%3Alightslategray%7D%5D%2C%5BSummary_of_Sales_by_Year%7Bbg%3Alightslategray%7D%5D%2C%5BSummary_of_Sales_by_Years%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BSummary_of_Sales_by_Year%5D%2C%5BSummary_of_Sales_by_Quarters%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BSummary_of_Sales_by_Quarter%5D%2C%5BSales_Totals_by_Amounts%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BSales_Totals_by_Amount%5D%2C%5BSales_by_Categories%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BSales_by_Category%5D%2C%5BProducts_by_Categories%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BProducts_by_Category%5D%2C%5BProducts_Above_Average_Prices%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BProducts_Above_Average_Price%5D%2C%5BProduct_Sales_for_1997%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BProduct_Sales_for_1997%5D%2C%5BOrders_Qries%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BOrders_Qry%5D%2C%5BOrder_Subtotals%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BOrder_Subtotal%5D%2C%5BOrder_Details_Extendeds%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BOrder_Details_Extended%5D%2C%5BInvoices%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BInvoice%5D%2C%5BCustomer_and_Suppliers_by_Cities%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BCustomer_and_Suppliers_by_City%5D%2C%5BCurrent_Product_Lists%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BCurrent_Product_List%5D%2C%5BCategory_Sales_for_1997%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BCategory_Sales_for_1997%5D%2C%5BAlphabetical_list_of_products%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BAlphabetical_list_of_product%5D%2C%5BTerritories%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BTerritory%5D%2C%5BSuppliers%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BSupplier%5D%2C%5BShippers%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BShipper%5D%2C%5BRegions%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BRegion%5D%2C%5BProducts%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BProduct%5D%2C%5BOrders%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BOrder%5D%2C%5BOrder_Details%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BOrder_Detail%5D%2C%5BEmployees%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BEmployee%5D%2C%5BCustomers%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BCustomer%5D%2C%5BCustomerDemographics%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BCustomerDemographic%5D%2C%5BCategories%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BCategory%5D.svg)\n\n#### Legend\n", "version": "" }, "x-sap-api-type": "ODATAV4", diff --git a/test/lib/compile/data/People.openapi3.json b/test/lib/compile/data/People.openapi3.json index df2ecbc..adbfb48 100644 --- a/test/lib/compile/data/People.openapi3.json +++ b/test/lib/compile/data/People.openapi3.json @@ -2,7 +2,7 @@ "openapi": "3.0.2", "info": { "title": "Use the title annotation on your CDS service to provide a meaningful title.", - "description": "Use the Core.LongDescription or Core.Description annotation on your CDS service to provide a meaningful description.\n\n## Entity Data Model\n![ER Diagram](https://yuml.me/diagram/class/[Supplier{bg:lightslategray}],[Supplier]++-0..1[Address],[Supplier]-*>[ProductService.Product{bg:whitesmoke}],[Address],[Person{bg:lightslategray}],[Person]^[Customer{bg:lightslategray}],[Person]^[Employee{bg:lightslategray}],[PersonDetail{bg:lightslategray}],[PersonDetail]++-0..1[Address],[PersonDetail]0..1-0..1[Person],[PersonDetails%20{bg:lawngreen}]++-*>[PersonDetail],[People%20{bg:lawngreen}]++-*>[Person],[Suppliers%20{bg:lawngreen}]++-*>[Supplier])\n\n### Legend\n![Legend](https://yuml.me/diagram/plain;dir:TB;scale:60/class/[External.Type{bg:whitesmoke}],[ComplexType],[EntityType{bg:lightslategray}],[EntitySet/Singleton/Operation{bg:lawngreen}])", + "description": "Use the Core.LongDescription or Core.Description annotation on your CDS service to provide a meaningful description.\n\n### Entity Data Model\n[![ER Diagram](https://app.yuml.me/diagram/v1/class/plain/%5BSupplier%7Bbg%3Alightslategray%7D%5D%2C%5BSupplier%5D%2B%2B-0..1%5BAddress%5D%2C%5BSupplier%5D-*%3E%5BProductService.Product%7Bbg%3Awhitesmoke%7D%5D%2C%5BAddress%5D%2C%5BPerson%7Bbg%3Alightslategray%7D%5D%2C%5BPerson%5D%5E%5BCustomer%7Bbg%3Alightslategray%7D%5D%2C%5BPerson%5D%5E%5BEmployee%7Bbg%3Alightslategray%7D%5D%2C%5BPersonDetail%7Bbg%3Alightslategray%7D%5D%2C%5BPersonDetail%5D%2B%2B-0..1%5BAddress%5D%2C%5BPersonDetail%5D0..1-0..1%5BPerson%5D%2C%5BPersonDetails%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BPersonDetail%5D%2C%5BPeople%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BPerson%5D%2C%5BSuppliers%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BSupplier%5D.svg)](https://app.yuml.me/diagram/v1/class/plain/%5BSupplier%7Bbg%3Alightslategray%7D%5D%2C%5BSupplier%5D%2B%2B-0..1%5BAddress%5D%2C%5BSupplier%5D-*%3E%5BProductService.Product%7Bbg%3Awhitesmoke%7D%5D%2C%5BAddress%5D%2C%5BPerson%7Bbg%3Alightslategray%7D%5D%2C%5BPerson%5D%5E%5BCustomer%7Bbg%3Alightslategray%7D%5D%2C%5BPerson%5D%5E%5BEmployee%7Bbg%3Alightslategray%7D%5D%2C%5BPersonDetail%7Bbg%3Alightslategray%7D%5D%2C%5BPersonDetail%5D%2B%2B-0..1%5BAddress%5D%2C%5BPersonDetail%5D0..1-0..1%5BPerson%5D%2C%5BPersonDetails%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BPersonDetail%5D%2C%5BPeople%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BPerson%5D%2C%5BSuppliers%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BSupplier%5D.svg)\n\n#### Legend\n", "version": "" }, "x-sap-api-type": "ODATAV4", @@ -737,6 +737,68 @@ } } }, + "/PersonDetails({PersonID})/Photo": { + "parameters": [ + { + "description": "key: PersonID", + "in": "path", + "name": "PersonID", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + } + } + ], + "get": { + "summary": "Retrieves photo of a single person detail.", + "tags": [ + "Person Details" + ], + "responses": { + "200": { + "description": "Retrieved photo", + "content": { + "*/*": { + "schema": { + "type": "string", + "format": "binary" + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/error" + } + } + }, + "put": { + "summary": "Changes photo of a single person detail.", + "tags": [ + "Person Details" + ], + "requestBody": { + "description": "New value for photo", + "required": true, + "content": { + "*/*": { + "schema": { + "type": "string", + "format": "binary" + } + } + } + }, + "responses": { + "204": { + "description": "Success" + }, + "4XX": { + "$ref": "#/components/responses/error" + } + } + } + }, "/Suppliers": { "get": { "summary": "Retrieves a list of suppliers.", diff --git a/test/lib/compile/data/Products.openapi3.json b/test/lib/compile/data/Products.openapi3.json index 9c2c67b..52b8026 100644 --- a/test/lib/compile/data/Products.openapi3.json +++ b/test/lib/compile/data/Products.openapi3.json @@ -2,7 +2,7 @@ "openapi": "3.0.2", "info": { "title": "Use the title annotation on your CDS service to provide a meaningful title.", - "description": "Use the Core.LongDescription or Core.Description annotation on your CDS service to provide a meaningful description.\n\n## Entity Data Model\n![ER Diagram](https://yuml.me/diagram/class/[Product{bg:lightslategray}],[Product]*-*[Category],[Product]-0..1>[PeopleService.Supplier{bg:whitesmoke}],[Product]^[FeaturedProduct{bg:lightslategray}],[FeaturedProduct]0..1-0..1[Advertisement],[ProductDetail{bg:lightslategray}],[ProductDetail]0..1-0..1[Product],[Category{bg:lightslategray}],[Advertisement{bg:lightslategray}],[Advertisements%20{bg:lawngreen}]++-*>[Advertisement],[Categories%20{bg:lawngreen}]++-*>[Category],[ProductDetails%20{bg:lawngreen}]++-*>[ProductDetail],[Products%20{bg:lawngreen}]++-*>[Product])\n\n### Legend\n![Legend](https://yuml.me/diagram/plain;dir:TB;scale:60/class/[External.Type{bg:whitesmoke}],[ComplexType],[EntityType{bg:lightslategray}],[EntitySet/Singleton/Operation{bg:lawngreen}])", + "description": "Use the Core.LongDescription or Core.Description annotation on your CDS service to provide a meaningful description.\n\n### Entity Data Model\n[![ER Diagram](https://app.yuml.me/diagram/v1/class/plain/%5BProduct%7Bbg%3Alightslategray%7D%5D%2C%5BProduct%5D*-*%5BCategory%5D%2C%5BProduct%5D-0..1%3E%5BPeopleService.Supplier%7Bbg%3Awhitesmoke%7D%5D%2C%5BProduct%5D%5E%5BFeaturedProduct%7Bbg%3Alightslategray%7D%5D%2C%5BFeaturedProduct%5D0..1-0..1%5BAdvertisement%5D%2C%5BProductDetail%7Bbg%3Alightslategray%7D%5D%2C%5BProductDetail%5D0..1-0..1%5BProduct%5D%2C%5BCategory%7Bbg%3Alightslategray%7D%5D%2C%5BAdvertisement%7Bbg%3Alightslategray%7D%5D%2C%5BAdvertisements%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BAdvertisement%5D%2C%5BCategories%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BCategory%5D%2C%5BProductDetails%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BProductDetail%5D%2C%5BProducts%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BProduct%5D.svg)](https://app.yuml.me/diagram/v1/class/plain/%5BProduct%7Bbg%3Alightslategray%7D%5D%2C%5BProduct%5D*-*%5BCategory%5D%2C%5BProduct%5D-0..1%3E%5BPeopleService.Supplier%7Bbg%3Awhitesmoke%7D%5D%2C%5BProduct%5D%5E%5BFeaturedProduct%7Bbg%3Alightslategray%7D%5D%2C%5BFeaturedProduct%5D0..1-0..1%5BAdvertisement%5D%2C%5BProductDetail%7Bbg%3Alightslategray%7D%5D%2C%5BProductDetail%5D0..1-0..1%5BProduct%5D%2C%5BCategory%7Bbg%3Alightslategray%7D%5D%2C%5BAdvertisement%7Bbg%3Alightslategray%7D%5D%2C%5BAdvertisements%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BAdvertisement%5D%2C%5BCategories%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BCategory%5D%2C%5BProductDetails%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BProductDetail%5D%2C%5BProducts%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BProduct%5D.svg)\n\n#### Legend\n", "version": "" }, "x-sap-api-type": "ODATAV4", @@ -322,6 +322,69 @@ } } }, + "/Advertisements({ID})/$value": { + "parameters": [ + { + "description": "key: ID", + "in": "path", + "name": "ID", + "required": true, + "schema": { + "type": "string", + "format": "uuid", + "example": "01234567-89ab-cdef-0123-456789abcdef" + } + } + ], + "get": { + "summary": "Retrieves the media stream of a single advertisement.", + "tags": [ + "Advertisements" + ], + "responses": { + "200": { + "description": "Retrieved advertisement", + "content": { + "*/*": { + "schema": { + "type": "string", + "format": "binary" + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/error" + } + } + }, + "put": { + "summary": "Changes the media stream of a single advertisement.", + "tags": [ + "Advertisements" + ], + "requestBody": { + "description": "New media stream for advertisement", + "required": true, + "content": { + "*/*": { + "schema": { + "type": "string", + "format": "binary" + } + } + } + }, + "responses": { + "204": { + "description": "Success" + }, + "4XX": { + "$ref": "#/components/responses/error" + } + } + } + }, "/Advertisements({ID})/FeaturedProduct": { "parameters": [ { diff --git a/test/lib/compile/data/TripPin.openapi3.json b/test/lib/compile/data/TripPin.openapi3.json index 31bb1a5..beacf93 100644 --- a/test/lib/compile/data/TripPin.openapi3.json +++ b/test/lib/compile/data/TripPin.openapi3.json @@ -2,7 +2,7 @@ "openapi": "3.0.2", "info": { "title": "TripPin service is a sample service for OData V4.", - "description": "This service is located at [https://services.odata.org/V4/(S(cnbm44wtbc1v5bgrlek5lpcc))/TripPinServiceRW/](https://services.odata.org/V4/%28S%28cnbm44wtbc1v5bgrlek5lpcc%29%29/TripPinServiceRW/)\n\n## Entity Data Model\n![ER Diagram](https://yuml.me/diagram/class/[City],[Location],[Location]++-[City],[Location]^[EventLocation],[Location]^[AirportLocation],[Photo{bg:lightslategray}],[Person{bg:lightslategray}],[Person]++-*[Location],[Person]++-0..1[PersonGender],[Person]-*>[Person],[Person]++-*>[Trip],[Person]-0..1>[Photo],[Airline{bg:lightslategray}],[Airport{bg:lightslategray}],[Airport]++-[AirportLocation],[PlanItem{bg:lightslategray}],[PlanItem]^[PublicTransportation{bg:lightslategray}],[PublicTransportation]^[Flight{bg:lightslategray}],[Flight]->[Airport],[Flight]->[Airport],[Flight]->[Airline],[PlanItem]^[Event{bg:lightslategray}],[Event]++-[EventLocation],[Trip{bg:lightslategray}],[Trip]-*>[Photo],[Trip]++-*>[PlanItem],[ResetDataSource{bg:lawngreen}],[GetNearestAirport{bg:lawngreen}]->[Airport],[Me%20{bg:lawngreen}]++->[Person],[Airports%20{bg:lawngreen}]++-*>[Airport],[Airlines%20{bg:lawngreen}]++-*>[Airline],[People%20{bg:lawngreen}]++-*>[Person],[Photos%20{bg:lawngreen}]++-*>[Photo])\n\n### Legend\n![Legend](https://yuml.me/diagram/plain;dir:TB;scale:60/class/[External.Type{bg:whitesmoke}],[ComplexType],[EntityType{bg:lightslategray}],[EntitySet/Singleton/Operation{bg:lawngreen}])", + "description": "This service is located at [https://services.odata.org/V4/(S(cnbm44wtbc1v5bgrlek5lpcc))/TripPinServiceRW/](https://services.odata.org/V4/%28S%28cnbm44wtbc1v5bgrlek5lpcc%29%29/TripPinServiceRW/)\n\n### Entity Data Model\n[![ER Diagram](https://app.yuml.me/diagram/v1/class/plain/%5BCity%5D%2C%5BLocation%5D%2C%5BLocation%5D%2B%2B-%5BCity%5D%2C%5BLocation%5D%5E%5BEventLocation%5D%2C%5BLocation%5D%5E%5BAirportLocation%5D%2C%5BPhoto%7Bbg%3Alightslategray%7D%5D%2C%5BPerson%7Bbg%3Alightslategray%7D%5D%2C%5BPerson%5D%2B%2B-*%5BLocation%5D%2C%5BPerson%5D%2B%2B-0..1%5BPersonGender%5D%2C%5BPerson%5D-*%3E%5BPerson%5D%2C%5BPerson%5D%2B%2B-*%3E%5BTrip%5D%2C%5BPerson%5D-0..1%3E%5BPhoto%5D%2C%5BAirline%7Bbg%3Alightslategray%7D%5D%2C%5BAirport%7Bbg%3Alightslategray%7D%5D%2C%5BAirport%5D%2B%2B-%5BAirportLocation%5D%2C%5BPlanItem%7Bbg%3Alightslategray%7D%5D%2C%5BPlanItem%5D%5E%5BPublicTransportation%7Bbg%3Alightslategray%7D%5D%2C%5BPublicTransportation%5D%5E%5BFlight%7Bbg%3Alightslategray%7D%5D%2C%5BFlight%5D-%3E%5BAirport%5D%2C%5BFlight%5D-%3E%5BAirport%5D%2C%5BFlight%5D-%3E%5BAirline%5D%2C%5BPlanItem%5D%5E%5BEvent%7Bbg%3Alightslategray%7D%5D%2C%5BEvent%5D%2B%2B-%5BEventLocation%5D%2C%5BTrip%7Bbg%3Alightslategray%7D%5D%2C%5BTrip%5D-*%3E%5BPhoto%5D%2C%5BTrip%5D%2B%2B-*%3E%5BPlanItem%5D%2C%5BResetDataSource%7Bbg%3Alawngreen%7D%5D%2C%5BGetNearestAirport%7Bbg%3Alawngreen%7D%5D-%3E%5BAirport%5D%2C%5BMe%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-%3E%5BPerson%5D%2C%5BAirports%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BAirport%5D%2C%5BAirlines%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BAirline%5D%2C%5BPeople%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BPerson%5D%2C%5BPhotos%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BPhoto%5D.svg)](https://app.yuml.me/diagram/v1/class/plain/%5BCity%5D%2C%5BLocation%5D%2C%5BLocation%5D%2B%2B-%5BCity%5D%2C%5BLocation%5D%5E%5BEventLocation%5D%2C%5BLocation%5D%5E%5BAirportLocation%5D%2C%5BPhoto%7Bbg%3Alightslategray%7D%5D%2C%5BPerson%7Bbg%3Alightslategray%7D%5D%2C%5BPerson%5D%2B%2B-*%5BLocation%5D%2C%5BPerson%5D%2B%2B-0..1%5BPersonGender%5D%2C%5BPerson%5D-*%3E%5BPerson%5D%2C%5BPerson%5D%2B%2B-*%3E%5BTrip%5D%2C%5BPerson%5D-0..1%3E%5BPhoto%5D%2C%5BAirline%7Bbg%3Alightslategray%7D%5D%2C%5BAirport%7Bbg%3Alightslategray%7D%5D%2C%5BAirport%5D%2B%2B-%5BAirportLocation%5D%2C%5BPlanItem%7Bbg%3Alightslategray%7D%5D%2C%5BPlanItem%5D%5E%5BPublicTransportation%7Bbg%3Alightslategray%7D%5D%2C%5BPublicTransportation%5D%5E%5BFlight%7Bbg%3Alightslategray%7D%5D%2C%5BFlight%5D-%3E%5BAirport%5D%2C%5BFlight%5D-%3E%5BAirport%5D%2C%5BFlight%5D-%3E%5BAirline%5D%2C%5BPlanItem%5D%5E%5BEvent%7Bbg%3Alightslategray%7D%5D%2C%5BEvent%5D%2B%2B-%5BEventLocation%5D%2C%5BTrip%7Bbg%3Alightslategray%7D%5D%2C%5BTrip%5D-*%3E%5BPhoto%5D%2C%5BTrip%5D%2B%2B-*%3E%5BPlanItem%5D%2C%5BResetDataSource%7Bbg%3Alawngreen%7D%5D%2C%5BGetNearestAirport%7Bbg%3Alawngreen%7D%5D-%3E%5BAirport%5D%2C%5BMe%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-%3E%5BPerson%5D%2C%5BAirports%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BAirport%5D%2C%5BAirlines%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BAirline%5D%2C%5BPeople%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BPerson%5D%2C%5BPhotos%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BPhoto%5D.svg)\n\n#### Legend\n", "version": "" }, "x-sap-api-type": "ODATAV4", diff --git a/test/lib/compile/data/aggregation.openapi3.json b/test/lib/compile/data/aggregation.openapi3.json index 3f3b3d5..3905fb3 100644 --- a/test/lib/compile/data/aggregation.openapi3.json +++ b/test/lib/compile/data/aggregation.openapi3.json @@ -2,7 +2,7 @@ "openapi": "3.0.2", "info": { "title": "Use the title annotation on your CDS service to provide a meaningful title.", - "description": "Use the Core.LongDescription or Core.Description annotation on your CDS service to provide a meaningful description.\n\n## Entity Data Model\n![ER Diagram](https://yuml.me/diagram/class/[Category{bg:lightslategray}],[Category]-*>[Product],[Currency{bg:lightslategray}],[Customer{bg:lightslategray}],[Customer]-*>[Sales],[Product{bg:lightslategray}],[Product]-0..1>[Category],[Product]-*>[Sales],[Sales{bg:lightslategray}],[Sales]->[Customer],[Sales]->[Time],[Sales]->[Product],[Sales]->[SalesOrganization],[Sales]->[Currency],[SalesOrganization{bg:lightslategray}],[SalesOrganization]-0..1>[SalesOrganization],[Time{bg:lightslategray}],[Currencies%20{bg:lawngreen}]++-*>[Currency],[Sales%20{bg:lawngreen}]++-*>[Sales])\n\n### Legend\n![Legend](https://yuml.me/diagram/plain;dir:TB;scale:60/class/[External.Type{bg:whitesmoke}],[ComplexType],[EntityType{bg:lightslategray}],[EntitySet/Singleton/Operation{bg:lawngreen}])", + "description": "Use the Core.LongDescription or Core.Description annotation on your CDS service to provide a meaningful description.\n\n### Entity Data Model\n[![ER Diagram](https://app.yuml.me/diagram/v1/class/plain/%5BCategory%7Bbg%3Alightslategray%7D%5D%2C%5BCategory%5D-*%3E%5BProduct%5D%2C%5BCurrency%7Bbg%3Alightslategray%7D%5D%2C%5BCustomer%7Bbg%3Alightslategray%7D%5D%2C%5BCustomer%5D-*%3E%5BSales%5D%2C%5BProduct%7Bbg%3Alightslategray%7D%5D%2C%5BProduct%5D-0..1%3E%5BCategory%5D%2C%5BProduct%5D-*%3E%5BSales%5D%2C%5BSales%7Bbg%3Alightslategray%7D%5D%2C%5BSales%5D-%3E%5BCustomer%5D%2C%5BSales%5D-%3E%5BTime%5D%2C%5BSales%5D-%3E%5BProduct%5D%2C%5BSales%5D-%3E%5BSalesOrganization%5D%2C%5BSales%5D-%3E%5BCurrency%5D%2C%5BSalesOrganization%7Bbg%3Alightslategray%7D%5D%2C%5BSalesOrganization%5D-0..1%3E%5BSalesOrganization%5D%2C%5BTime%7Bbg%3Alightslategray%7D%5D%2C%5BCurrencies%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BCurrency%5D%2C%5BSales%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BSales%5D.svg)](https://app.yuml.me/diagram/v1/class/plain/%5BCategory%7Bbg%3Alightslategray%7D%5D%2C%5BCategory%5D-*%3E%5BProduct%5D%2C%5BCurrency%7Bbg%3Alightslategray%7D%5D%2C%5BCustomer%7Bbg%3Alightslategray%7D%5D%2C%5BCustomer%5D-*%3E%5BSales%5D%2C%5BProduct%7Bbg%3Alightslategray%7D%5D%2C%5BProduct%5D-0..1%3E%5BCategory%5D%2C%5BProduct%5D-*%3E%5BSales%5D%2C%5BSales%7Bbg%3Alightslategray%7D%5D%2C%5BSales%5D-%3E%5BCustomer%5D%2C%5BSales%5D-%3E%5BTime%5D%2C%5BSales%5D-%3E%5BProduct%5D%2C%5BSales%5D-%3E%5BSalesOrganization%5D%2C%5BSales%5D-%3E%5BCurrency%5D%2C%5BSalesOrganization%7Bbg%3Alightslategray%7D%5D%2C%5BSalesOrganization%5D-0..1%3E%5BSalesOrganization%5D%2C%5BTime%7Bbg%3Alightslategray%7D%5D%2C%5BCurrencies%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BCurrency%5D%2C%5BSales%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BSales%5D.svg)\n\n#### Legend\n", "version": "" }, "x-sap-api-type": "ODATAV4", diff --git a/test/lib/compile/data/annotations.openapi3.json b/test/lib/compile/data/annotations.openapi3.json index ac36152..b22e980 100644 --- a/test/lib/compile/data/annotations.openapi3.json +++ b/test/lib/compile/data/annotations.openapi3.json @@ -2,7 +2,7 @@ "openapi": "3.0.2", "info": { "title": "Service for namespace Supported.Annotations", - "description": "This service is located at [https://localhost/service-root/](https://localhost/service-root/)\n\n## Entity Data Model\n![ER Diagram](https://yuml.me/diagram/class/[SinglePartKey{bg:lightslategray}],[SinglePartKey]-0..1>[TwoPartKey],[SinglePartKey]-*>[TwoPartKey],[SinglePartKey]-0..1>[TwoPartKey],[SinglePartKey]-*>[TwoPartKey],[SinglePartKey]-0..1>[TwoPartKey],[SinglePartKey]-*>[TwoPartKey],[TwoPartKey{bg:lightslategray}],[TwoNothingSingleton%20{bg:lawngreen}]++->[TwoPartKey],[TwoWriteOnlySingleton%20{bg:lawngreen}]++->[TwoPartKey],[TwoNothingSet%20{bg:lawngreen}]++-*>[TwoPartKey],[TwoWriteOnlySet%20{bg:lawngreen}]++-*>[TwoPartKey],[TwoReadOnlyByKeySet%20{bg:lawngreen}]++-*>[TwoPartKey],[TwoReadOnlySet%20{bg:lawngreen}]++-*>[TwoPartKey],[TwoAllSet%20{bg:lawngreen}]++-*>[TwoPartKey],[ReadOnlySingleton%20{bg:lawngreen}]++->[SinglePartKey],[AllSingleton%20{bg:lawngreen}]++->[SinglePartKey],[ReadListOnlySet%20{bg:lawngreen}]++-*>[SinglePartKey],[OneNavigationSet%20{bg:lawngreen}]++-*>[SinglePartKey],[NoNavigationSet%20{bg:lawngreen}]++-*>[SinglePartKey],[AllSet%20{bg:lawngreen}]++-*>[SinglePartKey])\n\n### Legend\n![Legend](https://yuml.me/diagram/plain;dir:TB;scale:60/class/[External.Type{bg:whitesmoke}],[ComplexType],[EntityType{bg:lightslategray}],[EntitySet/Singleton/Operation{bg:lawngreen}])", + "description": "This service is located at [https://localhost/service-root/](https://localhost/service-root/)\n\n### Entity Data Model\n[![ER Diagram](https://app.yuml.me/diagram/v1/class/plain/%5BSinglePartKey%7Bbg%3Alightslategray%7D%5D%2C%5BSinglePartKey%5D-0..1%3E%5BTwoPartKey%5D%2C%5BSinglePartKey%5D-*%3E%5BTwoPartKey%5D%2C%5BSinglePartKey%5D-0..1%3E%5BTwoPartKey%5D%2C%5BSinglePartKey%5D-*%3E%5BTwoPartKey%5D%2C%5BSinglePartKey%5D-0..1%3E%5BTwoPartKey%5D%2C%5BSinglePartKey%5D-*%3E%5BTwoPartKey%5D%2C%5BTwoPartKey%7Bbg%3Alightslategray%7D%5D%2C%5BTwoNothingSingleton%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-%3E%5BTwoPartKey%5D%2C%5BTwoWriteOnlySingleton%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-%3E%5BTwoPartKey%5D%2C%5BTwoNothingSet%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BTwoPartKey%5D%2C%5BTwoWriteOnlySet%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BTwoPartKey%5D%2C%5BTwoReadOnlyByKeySet%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BTwoPartKey%5D%2C%5BTwoReadOnlySet%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BTwoPartKey%5D%2C%5BTwoAllSet%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BTwoPartKey%5D%2C%5BReadOnlySingleton%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-%3E%5BSinglePartKey%5D%2C%5BAllSingleton%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-%3E%5BSinglePartKey%5D%2C%5BReadListOnlySet%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BSinglePartKey%5D%2C%5BOneNavigationSet%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BSinglePartKey%5D%2C%5BNoNavigationSet%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BSinglePartKey%5D%2C%5BAllSet%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BSinglePartKey%5D.svg)](https://app.yuml.me/diagram/v1/class/plain/%5BSinglePartKey%7Bbg%3Alightslategray%7D%5D%2C%5BSinglePartKey%5D-0..1%3E%5BTwoPartKey%5D%2C%5BSinglePartKey%5D-*%3E%5BTwoPartKey%5D%2C%5BSinglePartKey%5D-0..1%3E%5BTwoPartKey%5D%2C%5BSinglePartKey%5D-*%3E%5BTwoPartKey%5D%2C%5BSinglePartKey%5D-0..1%3E%5BTwoPartKey%5D%2C%5BSinglePartKey%5D-*%3E%5BTwoPartKey%5D%2C%5BTwoPartKey%7Bbg%3Alightslategray%7D%5D%2C%5BTwoNothingSingleton%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-%3E%5BTwoPartKey%5D%2C%5BTwoWriteOnlySingleton%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-%3E%5BTwoPartKey%5D%2C%5BTwoNothingSet%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BTwoPartKey%5D%2C%5BTwoWriteOnlySet%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BTwoPartKey%5D%2C%5BTwoReadOnlyByKeySet%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BTwoPartKey%5D%2C%5BTwoReadOnlySet%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BTwoPartKey%5D%2C%5BTwoAllSet%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BTwoPartKey%5D%2C%5BReadOnlySingleton%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-%3E%5BSinglePartKey%5D%2C%5BAllSingleton%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-%3E%5BSinglePartKey%5D%2C%5BReadListOnlySet%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BSinglePartKey%5D%2C%5BOneNavigationSet%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BSinglePartKey%5D%2C%5BNoNavigationSet%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BSinglePartKey%5D%2C%5BAllSet%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BSinglePartKey%5D.svg)\n\n#### Legend\n", "version": "" }, "x-sap-api-type": "ODATAV4", diff --git a/test/lib/compile/data/authorization.openapi3.json b/test/lib/compile/data/authorization.openapi3.json index d5141f4..6b6434e 100644 --- a/test/lib/compile/data/authorization.openapi3.json +++ b/test/lib/compile/data/authorization.openapi3.json @@ -2,7 +2,7 @@ "openapi": "3.0.2", "info": { "title": "Service for namespace auth.example", - "description": "This service is located at [https://localhost/service-root/](https://localhost/service-root/)\n\n## Entity Data Model\n![ER Diagram](https://yuml.me/diagram/class/[Person{bg:lightslategray}],[People%20{bg:lawngreen}]++-*>[Person])\n\n### Legend\n![Legend](https://yuml.me/diagram/plain;dir:TB;scale:60/class/[External.Type{bg:whitesmoke}],[ComplexType],[EntityType{bg:lightslategray}],[EntitySet/Singleton/Operation{bg:lawngreen}])", + "description": "This service is located at [https://localhost/service-root/](https://localhost/service-root/)\n\n### Entity Data Model\n[![ER Diagram](https://app.yuml.me/diagram/v1/class/plain/%5BPerson%7Bbg%3Alightslategray%7D%5D%2C%5BPeople%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BPerson%5D.svg)](https://app.yuml.me/diagram/v1/class/plain/%5BPerson%7Bbg%3Alightslategray%7D%5D%2C%5BPeople%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BPerson%5D.svg)\n\n#### Legend\n", "version": "" }, "x-sap-api-type": "ODATAV4", diff --git a/test/lib/compile/data/autoexposed-direct.openapi3.json b/test/lib/compile/data/autoexposed-direct.openapi3.json index 2e8021a..d1cb590 100644 --- a/test/lib/compile/data/autoexposed-direct.openapi3.json +++ b/test/lib/compile/data/autoexposed-direct.openapi3.json @@ -675,4 +675,4 @@ } } } -} \ No newline at end of file +} diff --git a/test/lib/compile/data/containment.openapi3.json b/test/lib/compile/data/containment.openapi3.json index 458a9e7..9be0370 100644 --- a/test/lib/compile/data/containment.openapi3.json +++ b/test/lib/compile/data/containment.openapi3.json @@ -2,7 +2,7 @@ "openapi": "3.0.2", "info": { "title": "Service for namespace Containment", - "description": "This service is located at [https://localhost/service-root/](https://localhost/service-root/)\n\n## Entity Data Model\n![ER Diagram](https://yuml.me/diagram/class/[Whole{bg:lightslategray}],[Whole]++-0..1>[Part],[Whole]++-*>[Part],[Part{bg:lightslategray}],[Part]++-0..1>[SubPart],[Part]++-*>[SubPart],[Part]++-*>[SubPart],[Part]++-*>[SubPart],[SubPart{bg:lightslategray}],[Folder{bg:lightslategray}],[Folder]++-*>[Folder],[Folders%20{bg:lawngreen}]++-*>[Folder],[TheWhole%20{bg:lawngreen}]++->[Whole],[Wholes%20{bg:lawngreen}]++-*>[Whole])\n\n### Legend\n![Legend](https://yuml.me/diagram/plain;dir:TB;scale:60/class/[External.Type{bg:whitesmoke}],[ComplexType],[EntityType{bg:lightslategray}],[EntitySet/Singleton/Operation{bg:lawngreen}])", + "description": "This service is located at [https://localhost/service-root/](https://localhost/service-root/)\n\n### Entity Data Model\n[![ER Diagram](https://app.yuml.me/diagram/v1/class/plain/%5BWhole%7Bbg%3Alightslategray%7D%5D%2C%5BWhole%5D%2B%2B-0..1%3E%5BPart%5D%2C%5BWhole%5D%2B%2B-*%3E%5BPart%5D%2C%5BPart%7Bbg%3Alightslategray%7D%5D%2C%5BPart%5D%2B%2B-0..1%3E%5BSubPart%5D%2C%5BPart%5D%2B%2B-*%3E%5BSubPart%5D%2C%5BPart%5D%2B%2B-*%3E%5BSubPart%5D%2C%5BPart%5D%2B%2B-*%3E%5BSubPart%5D%2C%5BSubPart%7Bbg%3Alightslategray%7D%5D%2C%5BFolder%7Bbg%3Alightslategray%7D%5D%2C%5BFolder%5D%2B%2B-*%3E%5BFolder%5D%2C%5BFolders%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BFolder%5D%2C%5BTheWhole%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-%3E%5BWhole%5D%2C%5BWholes%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BWhole%5D.svg)](https://app.yuml.me/diagram/v1/class/plain/%5BWhole%7Bbg%3Alightslategray%7D%5D%2C%5BWhole%5D%2B%2B-0..1%3E%5BPart%5D%2C%5BWhole%5D%2B%2B-*%3E%5BPart%5D%2C%5BPart%7Bbg%3Alightslategray%7D%5D%2C%5BPart%5D%2B%2B-0..1%3E%5BSubPart%5D%2C%5BPart%5D%2B%2B-*%3E%5BSubPart%5D%2C%5BPart%5D%2B%2B-*%3E%5BSubPart%5D%2C%5BPart%5D%2B%2B-*%3E%5BSubPart%5D%2C%5BSubPart%7Bbg%3Alightslategray%7D%5D%2C%5BFolder%7Bbg%3Alightslategray%7D%5D%2C%5BFolder%5D%2B%2B-*%3E%5BFolder%5D%2C%5BFolders%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BFolder%5D%2C%5BTheWhole%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-%3E%5BWhole%5D%2C%5BWholes%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BWhole%5D.svg)\n\n#### Legend\n", "version": "" }, "x-sap-api-type": "ODATAV4", diff --git a/test/lib/compile/data/csdl-16.1.openapi3.json b/test/lib/compile/data/csdl-16.1.openapi3.json index 9daaa5b..80d3f1f 100644 --- a/test/lib/compile/data/csdl-16.1.openapi3.json +++ b/test/lib/compile/data/csdl-16.1.openapi3.json @@ -2,7 +2,7 @@ "openapi": "3.0.2", "info": { "title": "Service for namespace ODataDemo", - "description": "This service is located at [https://localhost/service-root/](https://localhost/service-root/)\n\n## Entity Data Model\n![ER Diagram](https://yuml.me/diagram/class/[Product{bg:lightslategray}],[Product]*-[Category],[Category{bg:lightslategray}],[Supplier{bg:lightslategray}],[Supplier]++-[Address],[Supplier]0..1-*[Product],[Country{bg:lightslategray}],[Address],[Address]-0..1>[Country],[ProductsByRating{bg:lawngreen}]-*>[Product],[Countries%20{bg:lawngreen}]++-*>[Country],[MainSupplier%20{bg:lawngreen}]++->[Supplier],[Suppliers%20{bg:lawngreen}]++-*>[Supplier],[Categories%20{bg:lawngreen}]++-*>[Category],[Products%20{bg:lawngreen}]++-*>[Product])\n\n### Legend\n![Legend](https://yuml.me/diagram/plain;dir:TB;scale:60/class/[External.Type{bg:whitesmoke}],[ComplexType],[EntityType{bg:lightslategray}],[EntitySet/Singleton/Operation{bg:lawngreen}])", + "description": "This service is located at [https://localhost/service-root/](https://localhost/service-root/)\n\n### Entity Data Model\n[![ER Diagram](https://app.yuml.me/diagram/v1/class/plain/%5BProduct%7Bbg%3Alightslategray%7D%5D%2C%5BProduct%5D*-%5BCategory%5D%2C%5BCategory%7Bbg%3Alightslategray%7D%5D%2C%5BSupplier%7Bbg%3Alightslategray%7D%5D%2C%5BSupplier%5D%2B%2B-%5BAddress%5D%2C%5BSupplier%5D0..1-*%5BProduct%5D%2C%5BCountry%7Bbg%3Alightslategray%7D%5D%2C%5BAddress%5D%2C%5BAddress%5D-0..1%3E%5BCountry%5D%2C%5BProductsByRating%7Bbg%3Alawngreen%7D%5D-*%3E%5BProduct%5D%2C%5BCountries%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BCountry%5D%2C%5BMainSupplier%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-%3E%5BSupplier%5D%2C%5BSuppliers%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BSupplier%5D%2C%5BCategories%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BCategory%5D%2C%5BProducts%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BProduct%5D.svg)](https://app.yuml.me/diagram/v1/class/plain/%5BProduct%7Bbg%3Alightslategray%7D%5D%2C%5BProduct%5D*-%5BCategory%5D%2C%5BCategory%7Bbg%3Alightslategray%7D%5D%2C%5BSupplier%7Bbg%3Alightslategray%7D%5D%2C%5BSupplier%5D%2B%2B-%5BAddress%5D%2C%5BSupplier%5D0..1-*%5BProduct%5D%2C%5BCountry%7Bbg%3Alightslategray%7D%5D%2C%5BAddress%5D%2C%5BAddress%5D-0..1%3E%5BCountry%5D%2C%5BProductsByRating%7Bbg%3Alawngreen%7D%5D-*%3E%5BProduct%5D%2C%5BCountries%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BCountry%5D%2C%5BMainSupplier%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-%3E%5BSupplier%5D%2C%5BSuppliers%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BSupplier%5D%2C%5BCategories%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BCategory%5D%2C%5BProducts%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BProduct%5D.svg)\n\n#### Legend\n", "version": "" }, "x-sap-api-type": "ODATAV4", diff --git a/test/lib/compile/data/custom-parameters.openapi3.json b/test/lib/compile/data/custom-parameters.openapi3.json index a194804..efebe4b 100644 --- a/test/lib/compile/data/custom-parameters.openapi3.json +++ b/test/lib/compile/data/custom-parameters.openapi3.json @@ -2,7 +2,7 @@ "openapi": "3.0.2", "info": { "title": "Service for namespace custom.parameters", - "description": "This service is located at [https://localhost/service-root/](https://localhost/service-root/)\n\n## Entity Data Model\n![ER Diagram](https://yuml.me/diagram/class/[ent{bg:lightslategray}],[func{bg:lawngreen}]-0..1>[ent],[act{bg:lawngreen}]-0..1>[ent],[sing%20{bg:lawngreen}]++-0..1>[ent],[ents%20{bg:lawngreen}]++-*>[ent])\n\n### Legend\n![Legend](https://yuml.me/diagram/plain;dir:TB;scale:60/class/[External.Type{bg:whitesmoke}],[ComplexType],[EntityType{bg:lightslategray}],[EntitySet/Singleton/Operation{bg:lawngreen}])", + "description": "This service is located at [https://localhost/service-root/](https://localhost/service-root/)\n\n### Entity Data Model\n[![ER Diagram](https://app.yuml.me/diagram/v1/class/plain/%5Bent%7Bbg%3Alightslategray%7D%5D%2C%5Bfunc%7Bbg%3Alawngreen%7D%5D-0..1%3E%5Bent%5D%2C%5Bact%7Bbg%3Alawngreen%7D%5D-0..1%3E%5Bent%5D%2C%5Bsing%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-0..1%3E%5Bent%5D%2C%5Bents%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5Bent%5D.svg)](https://app.yuml.me/diagram/v1/class/plain/%5Bent%7Bbg%3Alightslategray%7D%5D%2C%5Bfunc%7Bbg%3Alawngreen%7D%5D-0..1%3E%5Bent%5D%2C%5Bact%7Bbg%3Alawngreen%7D%5D-0..1%3E%5Bent%5D%2C%5Bsing%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-0..1%3E%5Bent%5D%2C%5Bents%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5Bent%5D.svg)\n\n#### Legend\n", "version": "" }, "x-sap-api-type": "ODATAV4", diff --git a/test/lib/compile/data/description-fallback.openapi3.json b/test/lib/compile/data/description-fallback.openapi3.json index 63ec641..257f14f 100644 --- a/test/lib/compile/data/description-fallback.openapi3.json +++ b/test/lib/compile/data/description-fallback.openapi3.json @@ -2,7 +2,7 @@ "openapi": "3.0.2", "info": { "title": "Use the title annotation on your CDS service to provide a meaningful title.", - "description": "Service with only Description annotation\n\n## Entity Data Model\n![ER Diagram](https://yuml.me/diagram/class/[Book{bg:lightslategray}],[doSomething{bg:lawngreen}],[Books%20{bg:lawngreen}]++-*>[Book])\n\n### Legend\n![Legend](https://yuml.me/diagram/plain;dir:TB;scale:60/class/[External.Type{bg:whitesmoke}],[ComplexType],[EntityType{bg:lightslategray}],[EntitySet/Singleton/Operation{bg:lawngreen}])", + "description": "Service with only Description annotation\n\n### Entity Data Model\n[![ER Diagram](https://app.yuml.me/diagram/v1/class/plain/%5BBook%7Bbg%3Alightslategray%7D%5D%2C%5BdoSomething%7Bbg%3Alawngreen%7D%5D%2C%5BBooks%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BBook%5D.svg)](https://app.yuml.me/diagram/v1/class/plain/%5BBook%7Bbg%3Alightslategray%7D%5D%2C%5BdoSomething%7Bbg%3Alawngreen%7D%5D%2C%5BBooks%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BBook%5D.svg)\n\n#### Legend\n", "version": "" }, "x-sap-api-type": "ODATAV4", diff --git a/test/lib/compile/data/descriptions.openapi3.json b/test/lib/compile/data/descriptions.openapi3.json index 7bba0a5..05cae56 100644 --- a/test/lib/compile/data/descriptions.openapi3.json +++ b/test/lib/compile/data/descriptions.openapi3.json @@ -2,7 +2,7 @@ "openapi": "3.0.2", "info": { "title": "Container - Label", - "description": "Container - LongDescription\n\n## Entity Data Model\n![ER Diagram](https://yuml.me/diagram/class/[entity{bg:lightslategray}],[entity]++-*>[subEntity],[entity]-*>[entity],[subEntity{bg:lightslategray}],[functionimport_no_descriptions{bg:lawngreen}],[functionimport_ext{bg:lawngreen}],[functionimport{bg:lawngreen}],[actionimport_no_descriptions{bg:lawngreen}],[actionimport_ext{bg:lawngreen}],[actionimport{bg:lawngreen}],[single_ext%20{bg:lawngreen}]++->[entity],[single%20{bg:lawngreen}]++-0..1>[entity],[entities_ext%20{bg:lawngreen}]++-*>[entity],[entities%20{bg:lawngreen}]++-*>[entity])\n\n### Legend\n![Legend](https://yuml.me/diagram/plain;dir:TB;scale:60/class/[External.Type{bg:whitesmoke}],[ComplexType],[EntityType{bg:lightslategray}],[EntitySet/Singleton/Operation{bg:lawngreen}])", + "description": "Container - LongDescription\n\n### Entity Data Model\n[![ER Diagram](https://app.yuml.me/diagram/v1/class/plain/%5Bentity%7Bbg%3Alightslategray%7D%5D%2C%5Bentity%5D%2B%2B-*%3E%5BsubEntity%5D%2C%5Bentity%5D-*%3E%5Bentity%5D%2C%5BsubEntity%7Bbg%3Alightslategray%7D%5D%2C%5Bfunctionimport_no_descriptions%7Bbg%3Alawngreen%7D%5D%2C%5Bfunctionimport_ext%7Bbg%3Alawngreen%7D%5D%2C%5Bfunctionimport%7Bbg%3Alawngreen%7D%5D%2C%5Bactionimport_no_descriptions%7Bbg%3Alawngreen%7D%5D%2C%5Bactionimport_ext%7Bbg%3Alawngreen%7D%5D%2C%5Bactionimport%7Bbg%3Alawngreen%7D%5D%2C%5Bsingle_ext%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-%3E%5Bentity%5D%2C%5Bsingle%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-0..1%3E%5Bentity%5D%2C%5Bentities_ext%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5Bentity%5D%2C%5Bentities%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5Bentity%5D.svg)](https://app.yuml.me/diagram/v1/class/plain/%5Bentity%7Bbg%3Alightslategray%7D%5D%2C%5Bentity%5D%2B%2B-*%3E%5BsubEntity%5D%2C%5Bentity%5D-*%3E%5Bentity%5D%2C%5BsubEntity%7Bbg%3Alightslategray%7D%5D%2C%5Bfunctionimport_no_descriptions%7Bbg%3Alawngreen%7D%5D%2C%5Bfunctionimport_ext%7Bbg%3Alawngreen%7D%5D%2C%5Bfunctionimport%7Bbg%3Alawngreen%7D%5D%2C%5Bactionimport_no_descriptions%7Bbg%3Alawngreen%7D%5D%2C%5Bactionimport_ext%7Bbg%3Alawngreen%7D%5D%2C%5Bactionimport%7Bbg%3Alawngreen%7D%5D%2C%5Bsingle_ext%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-%3E%5Bentity%5D%2C%5Bsingle%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-0..1%3E%5Bentity%5D%2C%5Bentities_ext%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5Bentity%5D%2C%5Bentities%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5Bentity%5D.svg)\n\n#### Legend\n", "version": "0.0.1" }, "x-sap-api-type": "ODATAV4", diff --git a/test/lib/compile/data/example.openapi3.json b/test/lib/compile/data/example.openapi3.json index f592216..b29eed5 100644 --- a/test/lib/compile/data/example.openapi3.json +++ b/test/lib/compile/data/example.openapi3.json @@ -2,7 +2,7 @@ "openapi": "3.0.2", "info": { "title": "Use the title annotation on your CDS service to provide a meaningful title.", - "description": "Use the Core.LongDescription or Core.Description annotation on your CDS service to provide a meaningful description.\n\n## Entity Data Model\n![ER Diagram](https://yuml.me/diagram/class/[Product{bg:lightslategray}],[Product]*-*[Category],[Product]^[FeaturedProduct{bg:lightslategray}],[FeaturedProduct]0..1-0..1[Advertisement],[ProductDetail{bg:lightslategray}],[ProductDetail]0..1-0..1[Product],[Category{bg:lightslategray}],[Supplier{bg:lightslategray}],[Supplier]++-0..1[Address],[Supplier]0..1-*[Product],[Address],[Person{bg:lightslategray}],[Person]^[Customer{bg:lightslategray}],[Person]^[Employee{bg:lightslategray}],[PersonDetail{bg:lightslategray}],[PersonDetail]++-0..1[Address],[PersonDetail]0..1-0..1[Person],[Advertisement{bg:lightslategray}],[IncreaseSalaries{bg:lawngreen}],[Advertisements%20{bg:lawngreen}]++-*>[Advertisement],[PersonDetails%20{bg:lawngreen}]++-*>[PersonDetail],[Persons%20{bg:lawngreen}]++-*>[Person],[Suppliers%20{bg:lawngreen}]++-*>[Supplier],[Categories%20{bg:lawngreen}]++-*>[Category],[ProductDetails%20{bg:lawngreen}]++-*>[ProductDetail],[Products%20{bg:lawngreen}]++-*>[Product])\n\n### Legend\n![Legend](https://yuml.me/diagram/plain;dir:TB;scale:60/class/[External.Type{bg:whitesmoke}],[ComplexType],[EntityType{bg:lightslategray}],[EntitySet/Singleton/Operation{bg:lawngreen}])", + "description": "Use the Core.LongDescription or Core.Description annotation on your CDS service to provide a meaningful description.\n\n### Entity Data Model\n[![ER Diagram](https://app.yuml.me/diagram/v1/class/plain/%5BProduct%7Bbg%3Alightslategray%7D%5D%2C%5BProduct%5D*-*%5BCategory%5D%2C%5BProduct%5D%5E%5BFeaturedProduct%7Bbg%3Alightslategray%7D%5D%2C%5BFeaturedProduct%5D0..1-0..1%5BAdvertisement%5D%2C%5BProductDetail%7Bbg%3Alightslategray%7D%5D%2C%5BProductDetail%5D0..1-0..1%5BProduct%5D%2C%5BCategory%7Bbg%3Alightslategray%7D%5D%2C%5BSupplier%7Bbg%3Alightslategray%7D%5D%2C%5BSupplier%5D%2B%2B-0..1%5BAddress%5D%2C%5BSupplier%5D0..1-*%5BProduct%5D%2C%5BAddress%5D%2C%5BPerson%7Bbg%3Alightslategray%7D%5D%2C%5BPerson%5D%5E%5BCustomer%7Bbg%3Alightslategray%7D%5D%2C%5BPerson%5D%5E%5BEmployee%7Bbg%3Alightslategray%7D%5D%2C%5BPersonDetail%7Bbg%3Alightslategray%7D%5D%2C%5BPersonDetail%5D%2B%2B-0..1%5BAddress%5D%2C%5BPersonDetail%5D0..1-0..1%5BPerson%5D%2C%5BAdvertisement%7Bbg%3Alightslategray%7D%5D%2C%5BIncreaseSalaries%7Bbg%3Alawngreen%7D%5D%2C%5BAdvertisements%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BAdvertisement%5D%2C%5BPersonDetails%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BPersonDetail%5D%2C%5BPersons%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BPerson%5D%2C%5BSuppliers%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BSupplier%5D%2C%5BCategories%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BCategory%5D%2C%5BProductDetails%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BProductDetail%5D%2C%5BProducts%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BProduct%5D.svg)](https://app.yuml.me/diagram/v1/class/plain/%5BProduct%7Bbg%3Alightslategray%7D%5D%2C%5BProduct%5D*-*%5BCategory%5D%2C%5BProduct%5D%5E%5BFeaturedProduct%7Bbg%3Alightslategray%7D%5D%2C%5BFeaturedProduct%5D0..1-0..1%5BAdvertisement%5D%2C%5BProductDetail%7Bbg%3Alightslategray%7D%5D%2C%5BProductDetail%5D0..1-0..1%5BProduct%5D%2C%5BCategory%7Bbg%3Alightslategray%7D%5D%2C%5BSupplier%7Bbg%3Alightslategray%7D%5D%2C%5BSupplier%5D%2B%2B-0..1%5BAddress%5D%2C%5BSupplier%5D0..1-*%5BProduct%5D%2C%5BAddress%5D%2C%5BPerson%7Bbg%3Alightslategray%7D%5D%2C%5BPerson%5D%5E%5BCustomer%7Bbg%3Alightslategray%7D%5D%2C%5BPerson%5D%5E%5BEmployee%7Bbg%3Alightslategray%7D%5D%2C%5BPersonDetail%7Bbg%3Alightslategray%7D%5D%2C%5BPersonDetail%5D%2B%2B-0..1%5BAddress%5D%2C%5BPersonDetail%5D0..1-0..1%5BPerson%5D%2C%5BAdvertisement%7Bbg%3Alightslategray%7D%5D%2C%5BIncreaseSalaries%7Bbg%3Alawngreen%7D%5D%2C%5BAdvertisements%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BAdvertisement%5D%2C%5BPersonDetails%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BPersonDetail%5D%2C%5BPersons%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BPerson%5D%2C%5BSuppliers%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BSupplier%5D%2C%5BCategories%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BCategory%5D%2C%5BProductDetails%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BProductDetail%5D%2C%5BProducts%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BProduct%5D.svg)\n\n#### Legend\n", "version": "" }, "x-sap-api-type": "ODATAV4", @@ -331,6 +331,69 @@ } } }, + "/Advertisements({ID})/$value": { + "parameters": [ + { + "description": "key: ID", + "in": "path", + "name": "ID", + "required": true, + "schema": { + "type": "string", + "format": "uuid", + "example": "01234567-89ab-cdef-0123-456789abcdef" + } + } + ], + "get": { + "summary": "Retrieves the media stream of a single advertisement.", + "tags": [ + "Advertisements" + ], + "responses": { + "200": { + "description": "Retrieved advertisement", + "content": { + "*/*": { + "schema": { + "type": "string", + "format": "binary" + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/error" + } + } + }, + "put": { + "summary": "Changes the media stream of a single advertisement.", + "tags": [ + "Advertisements" + ], + "requestBody": { + "description": "New media stream for advertisement", + "required": true, + "content": { + "*/*": { + "schema": { + "type": "string", + "format": "binary" + } + } + } + }, + "responses": { + "204": { + "description": "Success" + }, + "4XX": { + "$ref": "#/components/responses/error" + } + } + } + }, "/Advertisements({ID})/FeaturedProduct": { "parameters": [ { @@ -1225,6 +1288,68 @@ } } }, + "/PersonDetails({PersonID})/Photo": { + "parameters": [ + { + "description": "key: PersonID", + "in": "path", + "name": "PersonID", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + } + } + ], + "get": { + "summary": "Retrieves photo of a single person detail.", + "tags": [ + "Person Details" + ], + "responses": { + "200": { + "description": "Retrieved photo", + "content": { + "*/*": { + "schema": { + "type": "string", + "format": "binary" + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/error" + } + } + }, + "put": { + "summary": "Changes photo of a single person detail.", + "tags": [ + "Person Details" + ], + "requestBody": { + "description": "New value for photo", + "required": true, + "content": { + "*/*": { + "schema": { + "type": "string", + "format": "binary" + } + } + } + }, + "responses": { + "204": { + "description": "Success" + }, + "4XX": { + "$ref": "#/components/responses/error" + } + } + } + }, "/Persons": { "get": { "summary": "Retrieves a list of persons.", diff --git a/test/lib/compile/data/immutable-composition.openapi3.json b/test/lib/compile/data/immutable-composition.openapi3.json index 1444ff6..20891d4 100644 --- a/test/lib/compile/data/immutable-composition.openapi3.json +++ b/test/lib/compile/data/immutable-composition.openapi3.json @@ -2,7 +2,7 @@ "openapi": "3.0.2", "info": { "title": "Use the title annotation on your CDS service to provide a meaningful title.", - "description": "Use the Core.LongDescription or Core.Description annotation on your CDS service to provide a meaningful description.\n\n## Entity Data Model\n![ER Diagram](https://yuml.me/diagram/class/[Parent{bg:lightslategray}],[Parent]++->[Child],[Parent]++->[Child],[Child{bg:lightslategray}],[Parents%20{bg:lawngreen}]++-*>[Parent])\n\n### Legend\n![Legend](https://yuml.me/diagram/plain;dir:TB;scale:60/class/[External.Type{bg:whitesmoke}],[ComplexType],[EntityType{bg:lightslategray}],[EntitySet/Singleton/Operation{bg:lawngreen}])", + "description": "Use the Core.LongDescription or Core.Description annotation on your CDS service to provide a meaningful description.\n\n### Entity Data Model\n[![ER Diagram](https://app.yuml.me/diagram/v1/class/plain/%5BParent%7Bbg%3Alightslategray%7D%5D%2C%5BParent%5D%2B%2B-%3E%5BChild%5D%2C%5BParent%5D%2B%2B-%3E%5BChild%5D%2C%5BChild%7Bbg%3Alightslategray%7D%5D%2C%5BParents%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BParent%5D.svg)](https://app.yuml.me/diagram/v1/class/plain/%5BParent%7Bbg%3Alightslategray%7D%5D%2C%5BParent%5D%2B%2B-%3E%5BChild%5D%2C%5BParent%5D%2B%2B-%3E%5BChild%5D%2C%5BChild%7Bbg%3Alightslategray%7D%5D%2C%5BParents%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BParent%5D.svg)\n\n#### Legend\n", "version": "" }, "x-sap-api-type": "ODATAV4", diff --git a/test/lib/compile/data/miscellaneous.openapi3.json b/test/lib/compile/data/miscellaneous.openapi3.json index 54cacad..3aaf6dd 100644 --- a/test/lib/compile/data/miscellaneous.openapi3.json +++ b/test/lib/compile/data/miscellaneous.openapi3.json @@ -2,7 +2,7 @@ "openapi": "3.0.2", "info": { "title": "Use the title annotation on your CDS service to provide a meaningful title.", - "description": "Examples from Part 3: CSDL\n\n## Entity Data Model\n![ER Diagram](https://yuml.me/diagram/class/[Measurement],[Example7to11],[Product{bg:lightslategray}],[Product]*-[Category],[Product]-0..1>[Supplier],[Supplier{bg:lightslategray}],[Customer{bg:lightslategray}],[Order{bg:lightslategray}],[Category{bg:lightslategray}],[Employee{bg:lightslategray}],[Employee]-0..1>[Manager],[Employee]^[Manager{bg:lightslategray}],[Manager]-*>[Employee],[Category17{bg:lightslategray}],[Category18{bg:lightslategray}],[Category18]++-[EntityInfo],[EntityInfo],[OrderLine{bg:lightslategray}],[Dimensions],[Product22{bg:lightslategray}],[Product22]++-0..1[Dimensions],[Product22]++-0..1[Dimensions],[ShipmentBox{bg:lightslategray}],[ShipmentBox]++-0..1[Dimensions],[Size],[Size]++-0..1[Length],[Size]++-0..1[Weight],[Product2{bg:lightslategray}],[NullablePrimitiveTypes],[NullablePrimitiveTypes]++-0..1[Color],[NullablePrimitiveTypes]++-0..1[IntegerDecimal],[NonNullablePrimitiveTypes],[NonNullablePrimitiveTypes]++-[Color],[NonNullablePrimitiveTypes]++-[IntegerDecimal],[NonNullablePrimitiveTypes]++-[Text],[Weird{bg:lightslategray}],[Weird]++-[Core.Permission{bg:whitesmoke}],[Weird]++-0..1[Core.Permission{bg:whitesmoke}],[Address],[Address]-0..1>[City],[Address]-0..1>[Region],[Address]-0..1>[Country],[City{bg:lightslategray}],[Region{bg:lightslategray}],[Country{bg:lightslategray}],[Planet{bg:lightslategray}],[NavigationOnly],[NavigationOnly]-0..1>[Planet],[AnnotationOnly],[Order{bg:lightslategray}],[PersonType],[MovieType],[FriendType{bg:lightslategray}],[PersonType]^[DeveloperType],[ScrumTeamType],[ScrumTeamType]++-0..1[DeveloperType],[MovieType]^[ArchivedMovieType],[SomeThingType],[SomeThingType]++-*[PersonType],[SomeThingType]-*>[FriendType],[ChangeTrackingType],[Categories35%20{bg:lawngreen}]++-*>[Category],[Categories34%20{bg:lawngreen}]++-*>[Category],[ProductsByRating{bg:lawngreen}]-*>[Product],[LeaveRequestApproval{bg:lawngreen}],[MainSupplier%20{bg:lawngreen}]++->[Supplier],[Suppliers%20{bg:lawngreen}]++-*>[Supplier],[Categories%20{bg:lawngreen}]++-*>[Category],[Products%20{bg:lawngreen}]++-*>[Product],[TopSellingProducts{bg:lawngreen}]-*>[Product],[Orders%20{bg:lawngreen}]++-*>[Order],[PreferredCustomers%20{bg:lawngreen}]++-*>[Customer],[StandardCustomers%20{bg:lawngreen}]++-*>[Customer])\n\n### Legend\n![Legend](https://yuml.me/diagram/plain;dir:TB;scale:60/class/[External.Type{bg:whitesmoke}],[ComplexType],[EntityType{bg:lightslategray}],[EntitySet/Singleton/Operation{bg:lawngreen}])", + "description": "Examples from Part 3: CSDL\n\n### Entity Data Model\n[![ER Diagram](https://app.yuml.me/diagram/v1/class/plain/%5BMeasurement%5D%2C%5BExample7to11%5D%2C%5BProduct%7Bbg%3Alightslategray%7D%5D%2C%5BProduct%5D*-%5BCategory%5D%2C%5BProduct%5D-0..1%3E%5BSupplier%5D%2C%5BSupplier%7Bbg%3Alightslategray%7D%5D%2C%5BCustomer%7Bbg%3Alightslategray%7D%5D%2C%5BOrder%7Bbg%3Alightslategray%7D%5D%2C%5BCategory%7Bbg%3Alightslategray%7D%5D%2C%5BEmployee%7Bbg%3Alightslategray%7D%5D%2C%5BEmployee%5D-0..1%3E%5BManager%5D%2C%5BEmployee%5D%5E%5BManager%7Bbg%3Alightslategray%7D%5D%2C%5BManager%5D-*%3E%5BEmployee%5D%2C%5BCategory17%7Bbg%3Alightslategray%7D%5D%2C%5BCategory18%7Bbg%3Alightslategray%7D%5D%2C%5BCategory18%5D%2B%2B-%5BEntityInfo%5D%2C%5BEntityInfo%5D%2C%5BOrderLine%7Bbg%3Alightslategray%7D%5D%2C%5BDimensions%5D%2C%5BProduct22%7Bbg%3Alightslategray%7D%5D%2C%5BProduct22%5D%2B%2B-0..1%5BDimensions%5D%2C%5BProduct22%5D%2B%2B-0..1%5BDimensions%5D%2C%5BShipmentBox%7Bbg%3Alightslategray%7D%5D%2C%5BShipmentBox%5D%2B%2B-0..1%5BDimensions%5D%2C%5BSize%5D%2C%5BSize%5D%2B%2B-0..1%5BLength%5D%2C%5BSize%5D%2B%2B-0..1%5BWeight%5D%2C%5BProduct2%7Bbg%3Alightslategray%7D%5D%2C%5BNullablePrimitiveTypes%5D%2C%5BNullablePrimitiveTypes%5D%2B%2B-0..1%5BColor%5D%2C%5BNullablePrimitiveTypes%5D%2B%2B-0..1%5BIntegerDecimal%5D%2C%5BNonNullablePrimitiveTypes%5D%2C%5BNonNullablePrimitiveTypes%5D%2B%2B-%5BColor%5D%2C%5BNonNullablePrimitiveTypes%5D%2B%2B-%5BIntegerDecimal%5D%2C%5BNonNullablePrimitiveTypes%5D%2B%2B-%5BText%5D%2C%5BWeird%7Bbg%3Alightslategray%7D%5D%2C%5BWeird%5D%2B%2B-%5BCore.Permission%7Bbg%3Awhitesmoke%7D%5D%2C%5BWeird%5D%2B%2B-0..1%5BCore.Permission%7Bbg%3Awhitesmoke%7D%5D%2C%5BAddress%5D%2C%5BAddress%5D-0..1%3E%5BCity%5D%2C%5BAddress%5D-0..1%3E%5BRegion%5D%2C%5BAddress%5D-0..1%3E%5BCountry%5D%2C%5BCity%7Bbg%3Alightslategray%7D%5D%2C%5BRegion%7Bbg%3Alightslategray%7D%5D%2C%5BCountry%7Bbg%3Alightslategray%7D%5D%2C%5BPlanet%7Bbg%3Alightslategray%7D%5D%2C%5BNavigationOnly%5D%2C%5BNavigationOnly%5D-0..1%3E%5BPlanet%5D%2C%5BAnnotationOnly%5D%2C%5BOrder%7Bbg%3Alightslategray%7D%5D%2C%5BPersonType%5D%2C%5BMovieType%5D%2C%5BFriendType%7Bbg%3Alightslategray%7D%5D%2C%5BPersonType%5D%5E%5BDeveloperType%5D%2C%5BScrumTeamType%5D%2C%5BScrumTeamType%5D%2B%2B-0..1%5BDeveloperType%5D%2C%5BMovieType%5D%5E%5BArchivedMovieType%5D%2C%5BSomeThingType%5D%2C%5BSomeThingType%5D%2B%2B-*%5BPersonType%5D%2C%5BSomeThingType%5D-*%3E%5BFriendType%5D%2C%5BChangeTrackingType%5D%2C%5BCategories35%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BCategory%5D%2C%5BCategories34%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BCategory%5D%2C%5BProductsByRating%7Bbg%3Alawngreen%7D%5D-*%3E%5BProduct%5D%2C%5BLeaveRequestApproval%7Bbg%3Alawngreen%7D%5D%2C%5BMainSupplier%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-%3E%5BSupplier%5D%2C%5BSuppliers%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BSupplier%5D%2C%5BCategories%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BCategory%5D%2C%5BProducts%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BProduct%5D%2C%5BTopSellingProducts%7Bbg%3Alawngreen%7D%5D-*%3E%5BProduct%5D%2C%5BOrders%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BOrder%5D%2C%5BPreferredCustomers%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BCustomer%5D%2C%5BStandardCustomers%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BCustomer%5D.svg)](https://app.yuml.me/diagram/v1/class/plain/%5BMeasurement%5D%2C%5BExample7to11%5D%2C%5BProduct%7Bbg%3Alightslategray%7D%5D%2C%5BProduct%5D*-%5BCategory%5D%2C%5BProduct%5D-0..1%3E%5BSupplier%5D%2C%5BSupplier%7Bbg%3Alightslategray%7D%5D%2C%5BCustomer%7Bbg%3Alightslategray%7D%5D%2C%5BOrder%7Bbg%3Alightslategray%7D%5D%2C%5BCategory%7Bbg%3Alightslategray%7D%5D%2C%5BEmployee%7Bbg%3Alightslategray%7D%5D%2C%5BEmployee%5D-0..1%3E%5BManager%5D%2C%5BEmployee%5D%5E%5BManager%7Bbg%3Alightslategray%7D%5D%2C%5BManager%5D-*%3E%5BEmployee%5D%2C%5BCategory17%7Bbg%3Alightslategray%7D%5D%2C%5BCategory18%7Bbg%3Alightslategray%7D%5D%2C%5BCategory18%5D%2B%2B-%5BEntityInfo%5D%2C%5BEntityInfo%5D%2C%5BOrderLine%7Bbg%3Alightslategray%7D%5D%2C%5BDimensions%5D%2C%5BProduct22%7Bbg%3Alightslategray%7D%5D%2C%5BProduct22%5D%2B%2B-0..1%5BDimensions%5D%2C%5BProduct22%5D%2B%2B-0..1%5BDimensions%5D%2C%5BShipmentBox%7Bbg%3Alightslategray%7D%5D%2C%5BShipmentBox%5D%2B%2B-0..1%5BDimensions%5D%2C%5BSize%5D%2C%5BSize%5D%2B%2B-0..1%5BLength%5D%2C%5BSize%5D%2B%2B-0..1%5BWeight%5D%2C%5BProduct2%7Bbg%3Alightslategray%7D%5D%2C%5BNullablePrimitiveTypes%5D%2C%5BNullablePrimitiveTypes%5D%2B%2B-0..1%5BColor%5D%2C%5BNullablePrimitiveTypes%5D%2B%2B-0..1%5BIntegerDecimal%5D%2C%5BNonNullablePrimitiveTypes%5D%2C%5BNonNullablePrimitiveTypes%5D%2B%2B-%5BColor%5D%2C%5BNonNullablePrimitiveTypes%5D%2B%2B-%5BIntegerDecimal%5D%2C%5BNonNullablePrimitiveTypes%5D%2B%2B-%5BText%5D%2C%5BWeird%7Bbg%3Alightslategray%7D%5D%2C%5BWeird%5D%2B%2B-%5BCore.Permission%7Bbg%3Awhitesmoke%7D%5D%2C%5BWeird%5D%2B%2B-0..1%5BCore.Permission%7Bbg%3Awhitesmoke%7D%5D%2C%5BAddress%5D%2C%5BAddress%5D-0..1%3E%5BCity%5D%2C%5BAddress%5D-0..1%3E%5BRegion%5D%2C%5BAddress%5D-0..1%3E%5BCountry%5D%2C%5BCity%7Bbg%3Alightslategray%7D%5D%2C%5BRegion%7Bbg%3Alightslategray%7D%5D%2C%5BCountry%7Bbg%3Alightslategray%7D%5D%2C%5BPlanet%7Bbg%3Alightslategray%7D%5D%2C%5BNavigationOnly%5D%2C%5BNavigationOnly%5D-0..1%3E%5BPlanet%5D%2C%5BAnnotationOnly%5D%2C%5BOrder%7Bbg%3Alightslategray%7D%5D%2C%5BPersonType%5D%2C%5BMovieType%5D%2C%5BFriendType%7Bbg%3Alightslategray%7D%5D%2C%5BPersonType%5D%5E%5BDeveloperType%5D%2C%5BScrumTeamType%5D%2C%5BScrumTeamType%5D%2B%2B-0..1%5BDeveloperType%5D%2C%5BMovieType%5D%5E%5BArchivedMovieType%5D%2C%5BSomeThingType%5D%2C%5BSomeThingType%5D%2B%2B-*%5BPersonType%5D%2C%5BSomeThingType%5D-*%3E%5BFriendType%5D%2C%5BChangeTrackingType%5D%2C%5BCategories35%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BCategory%5D%2C%5BCategories34%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BCategory%5D%2C%5BProductsByRating%7Bbg%3Alawngreen%7D%5D-*%3E%5BProduct%5D%2C%5BLeaveRequestApproval%7Bbg%3Alawngreen%7D%5D%2C%5BMainSupplier%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-%3E%5BSupplier%5D%2C%5BSuppliers%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BSupplier%5D%2C%5BCategories%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BCategory%5D%2C%5BProducts%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BProduct%5D%2C%5BTopSellingProducts%7Bbg%3Alawngreen%7D%5D-*%3E%5BProduct%5D%2C%5BOrders%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BOrder%5D%2C%5BPreferredCustomers%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BCustomer%5D%2C%5BStandardCustomers%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BCustomer%5D.svg)\n\n#### Legend\n", "version": "" }, "x-sap-api-type": "ODATAV4", diff --git a/test/lib/compile/data/non-expandable.openapi3.json b/test/lib/compile/data/non-expandable.openapi3.json index 00955a6..1a20a3e 100644 --- a/test/lib/compile/data/non-expandable.openapi3.json +++ b/test/lib/compile/data/non-expandable.openapi3.json @@ -2,7 +2,7 @@ "openapi": "3.0.2", "info": { "title": "Use the title annotation on your CDS service to provide a meaningful title.", - "description": "Use the Core.LongDescription or Core.Description annotation on your CDS service to provide a meaningful description.\n\n## Entity Data Model\n![ER Diagram](https://yuml.me/diagram/class/[Books{bg:lightslategray}],[Books]++-*>[Pages],[Pages{bg:lightslategray}],[Pages]->[Books],[Pages%20{bg:lawngreen}]++-*>[Pages],[Books%20{bg:lawngreen}]++-*>[Books])\n\n### Legend\n![Legend](https://yuml.me/diagram/plain;dir:TB;scale:60/class/[External.Type{bg:whitesmoke}],[ComplexType],[EntityType{bg:lightslategray}],[EntitySet/Singleton/Operation{bg:lawngreen}])", + "description": "Use the Core.LongDescription or Core.Description annotation on your CDS service to provide a meaningful description.\n\n### Entity Data Model\n[![ER Diagram](https://app.yuml.me/diagram/v1/class/plain/%5BBooks%7Bbg%3Alightslategray%7D%5D%2C%5BBooks%5D%2B%2B-*%3E%5BPages%5D%2C%5BPages%7Bbg%3Alightslategray%7D%5D%2C%5BPages%5D-%3E%5BBooks%5D%2C%5BPages%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BPages%5D%2C%5BBooks%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BBooks%5D.svg)](https://app.yuml.me/diagram/v1/class/plain/%5BBooks%7Bbg%3Alightslategray%7D%5D%2C%5BBooks%5D%2B%2B-*%3E%5BPages%5D%2C%5BPages%7Bbg%3Alightslategray%7D%5D%2C%5BPages%5D-%3E%5BBooks%5D%2C%5BPages%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BPages%5D%2C%5BBooks%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BBooks%5D.svg)\n\n#### Legend\n", "version": "" }, "x-sap-api-type": "ODATAV4", diff --git a/test/lib/compile/data/parameter-with-both-descriptions.openapi3.json b/test/lib/compile/data/parameter-with-both-descriptions.openapi3.json index 069c7d6..48fcfe9 100644 --- a/test/lib/compile/data/parameter-with-both-descriptions.openapi3.json +++ b/test/lib/compile/data/parameter-with-both-descriptions.openapi3.json @@ -2,7 +2,7 @@ "openapi": "3.0.2", "info": { "title": "Use the title annotation on your CDS service to provide a meaningful title.", - "description": "Use the Core.LongDescription or Core.Description annotation on your CDS service to provide a meaningful description.\n\n## Entity Data Model\n![ER Diagram](https://yuml.me/diagram/class/[Item{bg:lightslategray}],[processItem{bg:lawngreen}],[Items%20{bg:lawngreen}]++-*>[Item])\n\n### Legend\n![Legend](https://yuml.me/diagram/plain;dir:TB;scale:60/class/[External.Type{bg:whitesmoke}],[ComplexType],[EntityType{bg:lightslategray}],[EntitySet/Singleton/Operation{bg:lawngreen}])", + "description": "Use the Core.LongDescription or Core.Description annotation on your CDS service to provide a meaningful description.\n\n### Entity Data Model\n[![ER Diagram](https://app.yuml.me/diagram/v1/class/plain/%5BItem%7Bbg%3Alightslategray%7D%5D%2C%5BprocessItem%7Bbg%3Alawngreen%7D%5D%2C%5BItems%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BItem%5D.svg)](https://app.yuml.me/diagram/v1/class/plain/%5BItem%7Bbg%3Alightslategray%7D%5D%2C%5BprocessItem%7Bbg%3Alawngreen%7D%5D%2C%5BItems%E2%80%8C%7Bbg%3Alawngreen%7D%5D%2B%2B-*%3E%5BItem%5D.svg)\n\n#### Legend\n", "version": "" }, "x-sap-api-type": "ODATAV4", diff --git a/test/lib/compile/diagram.test.js b/test/lib/compile/diagram.test.js new file mode 100644 index 0000000..b3d0e50 --- /dev/null +++ b/test/lib/compile/diagram.test.js @@ -0,0 +1,253 @@ +const { describe, test } = require('node:test'); +const assert = require('node:assert'); +const { Diagram } = require('../../../lib/compile/diagram'); +const { CSDLMeta } = require('../../../lib/compile/csdl'); + +function makeDiagram(csdl) { + return new Diagram(new CSDLMeta(csdl)); +} + +/** Extract the DSL string from the first yuml.me URL in the diagram markdown. */ +function extractDsl(diagramMarkdown) { + // Match everything between /plain/ and the last .svg before ) or ] + const match = diagramMarkdown.match(/\/plain\/(.+?)\.svg(?=[)\]])/); + return match ? decodeURIComponent(match[1]) : ''; +} + +describe('Diagram', () => { + describe('getResourceDiagram', () => { + test('returns empty string for empty entity container', () => { + const csdl = { + $Version: '4.01', + 'My.Service': { $Kind: 'Schema', EntityContainer: { $Kind: 'EntityContainer' } }, + }; + assert.strictEqual(makeDiagram(csdl).getResourceDiagram({}), ''); + }); + + test('generates diagram markdown with heading, ER link and legend for non-empty container', () => { + const csdl = { + $Version: '4.01', + 'My.Service': { Order: { $Kind: 'EntityType' } }, + }; + const result = makeDiagram(csdl).getResourceDiagram({ + Orders: { $Type: 'My.Service.Order', $Collection: true }, + }); + assert.ok(result.includes('### Entity Data Model'), 'should include heading'); + assert.ok(result.includes('ER Diagram'), 'should include ER diagram link'); + assert.ok(result.includes('Legend'), 'should include legend'); + }); + + test('entity type uses lightslategray color', () => { + const csdl = { + $Version: '4.01', + 'My.Service': { Order: { $Kind: 'EntityType' } }, + }; + const dsl = extractDsl(makeDiagram(csdl).getResourceDiagram({ + Orders: { $Type: 'My.Service.Order', $Collection: true }, + })); + assert.ok(dsl.includes('[Order{bg:lightslategray}]'), 'entity type should carry lightslategray color'); + }); + + test('complex type is included without entity color', () => { + const csdl = { + $Version: '4.01', + 'My.Service': { + Address: { $Kind: 'ComplexType' }, + Customer: { + $Kind: 'EntityType', + HomeAddress: { $Type: 'My.Service.Address' }, + }, + }, + }; + const dsl = extractDsl(makeDiagram(csdl).getResourceDiagram({ + Customers: { $Type: 'My.Service.Customer', $Collection: true }, + })); + assert.ok(dsl.includes('[Address]'), 'complex type should appear without extra color'); + assert.ok(!dsl.includes('[Address{'), 'complex type should not have a color annotation'); + }); + + test('inheritance is depicted with base-type arrow', () => { + const csdl = { + $Version: '4.01', + 'My.Service': { + Base: { $Kind: 'EntityType' }, + Child: { $Kind: 'EntityType', $BaseType: 'My.Service.Base' }, + }, + }; + const dsl = extractDsl(makeDiagram(csdl).getResourceDiagram({ + Children: { $Type: 'My.Service.Child', $Collection: true }, + })); + assert.ok(dsl.includes('[Base]^[Child'), 'should show ^-arrow from base type'); + }); + + test('navigation property links source and target type', () => { + const csdl = { + $Version: '4.01', + 'My.Service': { + Order: { + $Kind: 'EntityType', + Items: { $Kind: 'NavigationProperty', $Type: 'My.Service.Item', $Collection: true }, + }, + Item: { $Kind: 'EntityType' }, + }, + }; + const dsl = extractDsl(makeDiagram(csdl).getResourceDiagram({ + Orders: { $Type: 'My.Service.Order', $Collection: true }, + })); + assert.ok(dsl.includes('[Order]'), 'should include Order type'); + assert.ok(dsl.includes('[Item]'), 'should include Item type'); + assert.ok(dsl.includes('[Order]-'), 'should have arrow from Order'); + }); + + test('containment navigation property uses ++ notation', () => { + const csdl = { + $Version: '4.01', + 'My.Service': { + Order: { + $Kind: 'EntityType', + Items: { $Kind: 'NavigationProperty', $Type: 'My.Service.Item', $Collection: true, $ContainsTarget: true }, + }, + Item: { $Kind: 'EntityType' }, + }, + }; + const dsl = extractDsl(makeDiagram(csdl).getResourceDiagram({ + Orders: { $Type: 'My.Service.Order', $Collection: true }, + })); + assert.ok(dsl.includes('[Order]++-'), 'containment should use ++ notation'); + }); + + test('entity set node is disambiguated from entity type node with ZWNJ', () => { + const csdl = { + $Version: '4.01', + 'My.Service': { Order: { $Kind: 'EntityType' } }, + }; + const dsl = extractDsl(makeDiagram(csdl).getResourceDiagram({ + Orders: { $Type: 'My.Service.Order', $Collection: true }, + })); + assert.ok(dsl.includes('Orders‌'), 'entity set node should carry ZWNJ (U+200C)'); + }); + + test('singleton resource node uses lawngreen color', () => { + const csdl = { + $Version: '4.01', + 'My.Service': { Config: { $Kind: 'EntityType' } }, + }; + const dsl = extractDsl(makeDiagram(csdl).getResourceDiagram({ + AppConfig: { $Type: 'My.Service.Config' }, + })); + assert.ok(dsl.includes('AppConfig‌{bg:lawngreen}'), 'singleton should use lawngreen'); + }); + + test('unbound action import node appears in diagram', () => { + const csdl = { + $Version: '4.01', + 'My.Service': { + ResetAll: [{ $Kind: 'Action' }], + }, + }; + const dsl = extractDsl(makeDiagram(csdl).getResourceDiagram({ + Reset: { $Action: 'My.Service.ResetAll' }, + })); + assert.ok(dsl.includes('[Reset{bg:lawngreen}]'), 'action import should appear as resource node'); + }); + + test('unbound function import node appears in diagram', () => { + const csdl = { + $Version: '4.01', + 'My.Service': { + TopItems: [{ $Kind: 'Function', $ReturnType: { $Type: 'My.Service.Item', $Collection: true } }], + Item: { $Kind: 'EntityType' }, + }, + }; + const dsl = extractDsl(makeDiagram(csdl).getResourceDiagram({ + BestItems: { $Function: 'My.Service.TopItems' }, + })); + assert.ok(dsl.includes('[BestItems{bg:lawngreen}]'), 'function import should appear as resource node'); + }); + + test('generated ER URL points to yuml.me and is properly encoded', () => { + const csdl = { + $Version: '4.01', + 'My.Service': { Order: { $Kind: 'EntityType' } }, + }; + const result = makeDiagram(csdl).getResourceDiagram({ + Orders: { $Type: 'My.Service.Order', $Collection: true }, + }); + assert.ok(result.includes('app.yuml.me'), 'should point to yuml.me'); + const urlMatch = result.match(/\(https:\/\/app\.yuml\.me[^)]+\)/); + assert.ok(urlMatch, 'should contain a URL in parentheses'); + assert.ok(!urlMatch[0].includes(' '), 'URL should not contain unencoded spaces'); + }); + + test('bidirectional nav property is depicted only once', () => { + const csdl = { + $Version: '4.01', + 'My.Service': { + Order: { + $Kind: 'EntityType', + Items: { $Kind: 'NavigationProperty', $Type: 'My.Service.Item', $Collection: true, $Partner: 'Order' }, + }, + Item: { + $Kind: 'EntityType', + Order: { $Kind: 'NavigationProperty', $Type: 'My.Service.Order', $Partner: 'Items' }, + }, + }, + }; + const dsl = extractDsl(makeDiagram(csdl).getResourceDiagram({ + Orders: { $Type: 'My.Service.Order', $Collection: true }, + })); + const arrows = (dsl.match(/\[Order\][^,]*\[Item\]|\[Item\][^,]*\[Order\]/g) || []); + assert.strictEqual(arrows.length, 1, 'bidirectional nav property should produce exactly one arrow'); + }); + + test('collection nav property shows * cardinality', () => { + const csdl = { + $Version: '4.01', + 'My.Service': { + Order: { + $Kind: 'EntityType', + Items: { $Kind: 'NavigationProperty', $Type: 'My.Service.Item', $Collection: true }, + }, + Item: { $Kind: 'EntityType' }, + }, + }; + const dsl = extractDsl(makeDiagram(csdl).getResourceDiagram({ + Orders: { $Type: 'My.Service.Order', $Collection: true }, + })); + assert.ok(dsl.includes('-*>'), 'collection nav property should show * cardinality'); + }); + + test('nullable nav property shows 0..1 cardinality', () => { + const csdl = { + $Version: '4.01', + 'My.Service': { + Order: { + $Kind: 'EntityType', + Customer: { $Kind: 'NavigationProperty', $Type: 'My.Service.CustomerType', $Nullable: true }, + }, + CustomerType: { $Kind: 'EntityType' }, + }, + }; + const dsl = extractDsl(makeDiagram(csdl).getResourceDiagram({ + Orders: { $Type: 'My.Service.Order', $Collection: true }, + })); + assert.ok(dsl.includes('-0..1>'), 'nullable nav property should show 0..1 cardinality'); + }); + + test('external type (unresolved) carries whitesmoke background', () => { + const csdl = { + $Version: '4.01', + 'My.Service': { + Order: { + $Kind: 'EntityType', + Ext: { $Type: 'External.SomeType' }, + }, + }, + }; + const dsl = extractDsl(makeDiagram(csdl).getResourceDiagram({ + Orders: { $Type: 'My.Service.Order', $Collection: true }, + })); + assert.ok(dsl.includes('whitesmoke'), 'unresolved external type should carry whitesmoke color'); + }); + }); +});