diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index d5bb629..07f9dae 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -4,6 +4,7 @@ on: push: tags: - "v*" + - "!v*-beta*" jobs: build: diff --git a/.gitignore b/.gitignore index e54b66e..ea492ca 100644 --- a/.gitignore +++ b/.gitignore @@ -153,3 +153,12 @@ $RECYCLE.BIN/ bin service.ts service.ts.json +test/dist + +.yarn/* +!.yarn/patches +!.yarn/releases +!.yarn/plugins +!.yarn/sdks +!.yarn/versions +.pnp.* \ No newline at end of file diff --git a/package.json b/package.json index d813771..ad6a526 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cds2types", - "version": "2.6.1", + "version": "2.6.2", "description": "CLI to convert CDS models to Typescript interfaces and enumerations", "main": "./bin/cli.js", "repository": "git@github.com:mrbandler/cds2types.git", @@ -18,7 +18,8 @@ ], "scripts": { "start": "node", - "build": "tsc", + "build": "tsc --project tsconfig.build.json", + "test": "tsc --project tsconfig.test.json", "build:start": "yarn build && yarn start", "build:link": "yarn build && npm link" }, diff --git a/schema.cds b/schema.cds index e03a11f..bd65f74 100644 --- a/schema.cds +++ b/schema.cds @@ -1,54 +1,77 @@ -using { Currency, managed, sap } from '@sap/cds/common'; +using { + Currency, + managed, + sap, + cuid +} from '@sap/cds/common'; + namespace sap.capire.bookshop; +entity ArrayUsingEntity : cuid { + inlineArray : array of { + id : String; + quantity : Integer + }; + adressArray : array of Address; + compositoinField : Composition of many { + idComposition : String; + quantityComposition : Integer; + } +} + entity Books : managed { - key ID : Integer; - title : localized String(111); - descr : localized String(1111); - author : Association to Authors; - genre : Association to Genres; - stock : Integer; - price : Decimal(9,2); - currency : Currency; + key ID : Integer; + title : localized String(111); + descr : localized String(1111); + author : Association to Authors; + genre : Association to Genres; + stock : Integer; + price : Decimal(9, 2); + currency : Currency; } + type Gender : Integer enum { - NonBinary; - Male; - Female; + NonBinary = 1; + Male = 2; + Female = 3; } type NameStr : String(111); type Name { - firstname: NameStr; - lastname: NameStr; + firstname : NameStr; + lastname : NameStr; } type Address { - street: String; - houseNo: String; - town: String; - country: String; + street : String; + houseNo : String; + town : String; + country : String; } type Addresses : many Address; entity Authors : managed { - key ID : Integer; - name : Name; - gender : Gender; - addresses : Addresses; - dateOfBirth : Date; - dateOfDeath : Date; - placeOfBirth : String; - placeOfDeath : String; - books : Association to many Books on books.author = $self; + key ID : Integer; + name : Name; + gender : Gender; + addresses : Addresses; + dateOfBirth : Date; + dateOfDeath : Date; + placeOfBirth : String; + placeOfDeath : String; + books : Association to many Books + on books.author = $self; } -/** Hierarchically organized Code List for Genres */ +/** + * Hierarchically organized Code List for Genres + */ entity Genres : sap.common.CodeList { - key ID : Integer; - parent : Association to Genres; - children : Composition of many Genres on children.parent = $self; + key ID : Integer; + parent : Association to Genres; + children : Composition of many Genres + on children.parent = $self; } diff --git a/service.cds b/service.cds index aed42ca..b3680af 100644 --- a/service.cds +++ b/service.cds @@ -1,18 +1,48 @@ -using { sap.capire.bookshop as my } from './schema'; -service CatalogService @(path:'/browse') { +using {sap.capire.bookshop as my} from './schema'; - @readonly entity Books as SELECT from my.Books {*, - author.name as author - } excluding { createdBy, modifiedBy } +service CatalogService @(path : '/browse') { - actions { - action addRating (stars: Integer); - function getViewsCount() returns Integer; + entity ServiceEntity { + key id : UUID; + arrayComplex : array of arrayParameterType; + arraySimple : array of String; } - function getBooks(author : my.Authors.ID) returns array of my.Books; + entity ArrayUsingEntity as projection on my.ArrayUsingEntity; - @requires_: 'authenticated-user' - action submitOrder (book : Books.ID, amount: Integer); + @readonly + entity Books as + select from my.Books { + *, + author.name as author + } + excluding { + createdBy, + modifiedBy + } + + actions { + action addRating(stars : Integer); + function getViewsCount() returns Integer; + } + + function getBooks(author : my.Authors:ID) returns array of my.Books; + action unboudAction(simpleParameter : String, arrayParameter : array of arrayParameterType, typedParameter : typedParameterType) returns ActionReturnType; + + @requires_ : 'authenticated-user' + action submitOrder(book : Books:ID, amount : Integer); + + + type arrayParameterType : { + value : String; + } + + type typedParameterType : { + value : String; + } + + type ActionReturnType : { + success : Boolean; + } } diff --git a/src/cds.parser.ts b/src/cds.parser.ts index 6110e49..c32741d 100644 --- a/src/cds.parser.ts +++ b/src/cds.parser.ts @@ -43,7 +43,7 @@ import { ITypeAliasDefinition, } from "./utils/types"; -import _, { isElement } from "lodash"; +import _ from "lodash"; /** * Parses a compiled CDS JSON object. @@ -384,12 +384,21 @@ export class CDSParser { */ private parseParams( definition: ICsnActionDefinition | ICsnFunctionDefinition - ): Map { - const result: Map = new Map(); + ): Map { + const result: Map = new Map< + string, + ICsnParam | ITypeAliasDefinition + >(); if (definition.params) { for (const key in definition.params) { - if (definition.params.hasOwnProperty(key)) { + if (definition.params[key].items !== undefined) { + const value = this.parseArrayTypeAliasDef( + key, + definition.params[key] + ); + result.set(key, value); + } else if (definition.params.hasOwnProperty(key)) { const value = definition.params[key]; result.set(key, value as ICsnParam); } diff --git a/src/types/action.func.ts b/src/types/action.func.ts index ad64d7c..c99a0ca 100644 --- a/src/types/action.func.ts +++ b/src/types/action.func.ts @@ -1,10 +1,13 @@ import * as morph from "ts-morph"; -import { ICsnTypeRef, Kind, isTypeRef } from "../utils/cds.types"; +import { ICsnTypeRef, Kind, isTypeRef, Cardinality } from "../utils/cds.types"; import { BaseType } from "./base.type"; import { Entity } from "./entity"; -import { IActionFunctionDefinition } from "../utils/types"; +import { + IActionFunctionDefinition, + ITypeAliasDefinition, +} from "../utils/types"; /** * Action/Function toType return type. @@ -172,7 +175,7 @@ export class ActionFunction extends BaseType t.Name === typeRef.ref[0]); @@ -189,9 +192,19 @@ export class ActionFunction extends BaseType; + params?: Map; returns?: IActionFunctionReturns; } diff --git a/test/schema.test.ts b/test/schema.test.ts new file mode 100644 index 0000000..ad45c3a --- /dev/null +++ b/test/schema.test.ts @@ -0,0 +1,68 @@ +// This file should be compilable if the types were created correctly. + +import { sap } from "../service"; + +const address: sap.capire.bookshop.IAddress = { + street: "", + houseNo: "", + town: "", + country: "", +}; + +const author: sap.capire.bookshop.IAuthors = { + ID: 1, + name: { + firstname: "", + lastname: "", + }, + gender: sap.capire.bookshop.Gender.Female, + addresses: [[address]], + dateOfBirth: new Date(), + dateOfDeath: new Date(), + placeOfBirth: "", + placeOfDeath: "", + books: [], +}; + +const book: sap.capire.bookshop.IBooks = { + ID: 1, + title: "", + descr: "", + author: author, + author_ID: 1, + genre: { + ID: 1, + parent: { + ID: 2, + children: [], + name: "", + descr: "", + }, + name: "", + descr: "", + children: [], + }, + genre_ID: 1, + stock: 1, + price: 1, + currency: { + code: "", + descr: "", + name: "", + symbol: "", + }, + currency_code: "", +}; + +const arrayUsingEntity: sap.capire.bookshop.IArrayUsingEntity = { + ID: "", + inlineArray: [], + adressArray: [address], + compositoinField: [ + { + idComposition: "", + quantityComposition: 1, + up__ID: "1", + }, + ], +}; diff --git a/test/service.test.ts b/test/service.test.ts new file mode 100644 index 0000000..281f892 --- /dev/null +++ b/test/service.test.ts @@ -0,0 +1,95 @@ +// This file should be compilable if the types were created correctly. + +import { CatalogService } from "../service"; + +const serviceEntity: CatalogService.IServiceEntity = { + id: "", + arrayComplex: [ + { + value: "", + }, + ], + arraySimple: [""], +}; + +const arrayUsingEntity: CatalogService.IArrayUsingEntity = { + ID: "", + inlineArray: [], + adressArray: [ + { + street: "", + houseNo: "", + town: "", + country: "", + }, + ], + compositoinField: [ + { + idComposition: "", + quantityComposition: 1, + up__ID: "", + }, + ], +}; + +const book: CatalogService.IBooks = { + ID: 1, + title: "", + descr: "", + author: { + firstname: "", + lastname: "", + }, + genre: { + ID: 1, + parent: { + ID: 2, + children: [], + name: "", + descr: "", + }, + name: "", + descr: "", + children: [], + }, + genre_ID: 1, + stock: 1, + price: 1, + currency: { + code: "", + descr: "", + name: "", + symbol: "", + }, + currency_code: "", +}; + +const authorAddRatingAction: CatalogService.IBooks.actions.IActionAddRatingParams = { + stars: 1, +}; + +const authorGetViewsCountFunction: CatalogService.IBooks.actions.FuncGetViewsCountReturn = 1; + +const getBooksFunctionParams: CatalogService.IFuncGetBooksParams = { + author: 1, +}; + +const unboundActionParams: CatalogService.IActionUnboudActionParams = { + simpleParameter: "", + arrayParameter: [ + { + value: "", + }, + ], + typedParameter: { + value: "", + }, +}; +const unboundActionReturn: CatalogService.ActionUnboudActionReturn = { + success: true, +}; + +const actionSubmitOrderParams: CatalogService.IActionSubmitOrderParams = { + book: 1, + amount: 1, +}; diff --git a/tsconfig.build.json b/tsconfig.build.json new file mode 100644 index 0000000..b903a8e --- /dev/null +++ b/tsconfig.build.json @@ -0,0 +1,8 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "./bin", + "rootDir": "./src" + }, + "exclude": ["service.ts", "test"] +} diff --git a/tsconfig.json b/tsconfig.json index 21631bf..a6c657a 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -3,14 +3,12 @@ "target": "es5", "module": "commonjs", "lib": ["es6", "es2015", "dom"], - "outDir": "./bin", - "rootDir": "./src", + "rootDir": "./", "downlevelIteration": true, "strict": true, "types": ["node"], "noImplicitAny": false, "esModuleInterop": true, "removeComments": true - }, - "exclude": ["service.ts"] + } } diff --git a/tsconfig.test.json b/tsconfig.test.json new file mode 100644 index 0000000..6a18f2a --- /dev/null +++ b/tsconfig.test.json @@ -0,0 +1,8 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "./test/dist", + "rootDir": "./" + }, + "include": ["test/**/*.ts"] +}