cap-js / cds-typer Goto Github PK
View Code? Open in Web Editor NEWCDS type generator for JavaScript
License: Apache License 2.0
CDS type generator for JavaScript
License: Apache License 2.0
TypeScript
Given cds such as:
entity Something : cuid {
taggedElements : Composition of many {
hierarchyLevel : String enum {
oneTaggedElementHierarchyLevel
};
key elementGuid : String;
};
The following type is generated:
export function _SomethingAspect<TBase extends new (...args: any[]) => object>(Base: TBase) {
return class Something extends Base {
taggedElements?: __.Composition.of.many<Array< {
hierarchyLevel?: taggedElements_hierarchyLevel | null,
elementGuid?: string,
}>>;
};
}
Yet taggedElements_hierarchyLevel
is not defined.
I would've expected taggedElements_hierarchyLevel
to exist.
No response
- **OS**: Mac OS
- **Node**: v20.10.0
- **npm**: 10.2.3
- **cds-typer**: 0.12.0
- **cds**: 7.4.1
No response
No response
JavaScript, TypeScript
Projecting an entity B
on an anonymous type T
in another entity A
does not generate the projection.
B
should be generated as projection on A.T
.
With this sample model:
entity A {
key ID: UUID;
x: Composition of {
y: String;
}
}
entity B as projection on A.x;
The entity B
is not being generated at all.
- **OS**:
- **Node**:
- **npm**:
- **cds-typer**: 0.10.0
- **cds**:
No response
No response
TypeScript
Given the following valid CDS schema (as described in the docs: Composition of Aspects):
entity Users : cuid, managed {
name : String(255) @mandatory;
username : String(255) @mandatory;
roles : Composition of many {
key role : Association to UserRoles
};
roleGroups : Composition of many {
key roleGroup : Association to UserRoleGroups
};
}
entity UserRoles : cuid {
name : String(255) @mandatory;
description : String(500);
users : Composition of many Users.roles
on users.role = $self;
}
entity UserRoleGroups : cuid {
name : String(255) @mandatory;
description : String(500);
users : Composition of many Users.roleGroups
on users.roleGroup = $self;
}
cds-typer
generates the following invalid TS definitions:
export class User extends _._cuidAspect(_._managedAspect(_UserAspect(__.Entity))) {}
export class Users extends Array<User> {}
export function _UserRoleAspect<TBase extends new (...args: any[]) => object>(Base: TBase) {
return class UserRole extends Base {
name?: string | null;
description?: string | null;
users?: __.Composition.of.many<Users.roles>;
static actions: {
}
};
}
export class UserRole extends _._cuidAspect(_UserRoleAspect(__.Entity)) {}
export class UserRoles extends Array<UserRole> {}
export function _UserRoleGroupAspect<TBase extends new (...args: any[]) => object>(Base: TBase) {
return class UserRoleGroup extends Base {
name?: string | null;
description?: string | null;
users?: __.Composition.of.many<Users.roleGroups>;
static actions: {
}
};
}
This code results in TS errors:
index.ts:56:40 - error TS2702: 'Users' only refers to a type, but is being used as a namespace here.
56 users?: __.Composition.of.many<Users.roles>;
index.ts:70:40 - error TS2702: 'Users' only refers to a type, but is being used as a namespace here.
70 users?: __.Composition.of.many<Users.roleGroups>;
No errors in TS definitions.
Try to generate definitions and use them in your code for the following CDS schema:
entity Users : cuid, managed {
name : String(255) @mandatory;
username : String(255) @mandatory;
roles : Composition of many {
key role : Association to UserRoles
};
roleGroups : Composition of many {
key roleGroup : Association to UserRoleGroups
};
}
entity UserRoles : cuid {
name : String(255) @mandatory;
description : String(500);
users : Composition of many Users.roles
on users.role = $self;
}
entity UserRoleGroups : cuid {
name : String(255) @mandatory;
description : String(500);
users : Composition of many Users.roleGroups
on users.roleGroup = $self;
}
- **OS**: Windows 10
- **Node**: 18.17.1
- **yarn**: 4.0.2
- **cds-typer**: 0.15.0
- **cds**: 7.5.1
No response
No response
TypeScript
Given an action such as:
action test( @mandatory array : array of {
@mandatory testInput : String not null enum {
anEntry;
};
} not null)
Yields to a failed compilation with the error message:
CDSError: Could not (re)generate types for model. Could not read file content of *: Failed: /[...]/node_modules/@cap-js/cds-typer/lib/cli.js "*" --outputDirectory "/[...]/@cds-models"
<exit code:>
1
<stderr:>
/[...]/node_modules/@cap-js/cds-typer/lib/util.js:69
n = n.match(last)[0]
^
TypeError: n.match is not a function
at Object.singular4 (/[...]/node_modules/@cap-js/cds-typer/lib/util.js:69:15)
at Resolver.resolveType (/[...]/node_modules/@cap-js/cds-typer/lib/components/resolver.js:376:46)
at Resolver.resolveAndRequire (/[...]/node_modules/@cap-js/cds-typer/lib/components/resolver.js:220:31)
at StructuredInlineDeclarationResolver.visitElement (/[...]/node_modules/@cap-js/cds-typer/lib/components/inline.js:70:44)
at Visitor.visitElement (/[...]/node_modules/@cap-js/cds-typer/lib/visitor.js:459:47)
at StructuredInlineDeclarationResolver.resolveInlineDeclaration (/[...]/node_modules/@cap-js/cds-typer/lib/components/inline.js:43:57)
at #resolveInlineDeclarationType (/[...]/node_modules/@cap-js/cds-typer/lib/components/resolver.js:425:55)
at Resolver.resolveType (/[...]/node_modules/@cap-js/cds-typer/lib/components/resolver.js:396:47)
at Resolver.resolveType (/[...]/node_modules/@cap-js/cds-typer/lib/components/resolver.js:392:18)
at Resolver.resolveAndRequire (/[...]/node_modules/@cap-js/cds-typer/lib/components/resolver.js:220:31)
Node.js v20.10.0
CDSError: Could not (re)generate types for model. Could not read file content of *: Failed: /[...]/node_modules/@cap-js/cds-typer/lib/cli.js "*" --outputDirectory "/[...]/@cds-models"
<exit code:>
1
<stderr:>
/[...]/node_modules/@cap-js/cds-typer/lib/util.js:69
n = n.match(last)[0]
^
TypeError: n.match is not a function
at Object.singular4 (/[...]/node_modules/@cap-js/cds-typer/lib/util.js:69:15)
at Resolver.resolveType (/[...]/node_modules/@cap-js/cds-typer/lib/components/resolver.js:376:46)
at Resolver.resolveAndRequire (/[...]/node_modules/@cap-js/cds-typer/lib/components/resolver.js:220:31)
at StructuredInlineDeclarationResolver.visitElement (/[...]/node_modules/@cap-js/cds-typer/lib/components/inline.js:70:44)
at Visitor.visitElement (/[...]/node_modules/@cap-js/cds-typer/lib/visitor.js:459:47)
at StructuredInlineDeclarationResolver.resolveInlineDeclaration (/[...]/node_modules/@cap-js/cds-typer/lib/components/inline.js:43:57)
at #resolveInlineDeclarationType (/[...]/node_modules/@cap-js/cds-typer/lib/components/resolver.js:425:55)
at Resolver.resolveType (/[...]/node_modules/@cap-js/cds-typer/lib/components/resolver.js:396:47)
at Resolver.resolveType (/[...]/node_modules/@cap-js/cds-typer/lib/components/resolver.js:392:18)
at Resolver.resolveAndRequire (/[...]/node_modules/@cap-js/cds-typer/lib/components/resolver.js:220:31)
Node.js v20.10.0
I'd expect the compilation to work.
No response
- **OS**: MacOs
- **Node**: v20.10.0.
- **npm**:
- **cds-typer**: 0.13.0
- **cds**:7.4.2
No response
No response
Hi,
first up, great to finally see some native type generation support in CAP. The automatic regeneration via VS Code extension is also working great ๐ฅณ .
Unfortunately I stumbled upon an issue that I also remarked in the cds2types
project (mrbandler/cds2types#40). It concerns the handling/conversion of CDS Date
types.
I created a sample repository where the issue can be tested.
Basically the typed result of e.g. a SELECT
query wrongly marks a CDS Date
column as a JavaScript Date
type wherein it is actually just a formatted date string.
Regards,
Ludwig
TypeScript
Hi,
When importing the SAP Build Process Automation workflow runtime API from the Business Accelerator HUB, the cds-typer crashes with following error log:
Original file from SAP Business Accelerator HUB: SPA_Workflow_Runtime.json
Import commands tried:
cds-ts import SPA_Workflow_Runtime.json --from openapi
cds-ts import SPA_Workflow_Runtime.json --from openapi --as cds
Both resulting in the same error. (both generated files csn / cds are syntactically correct)
Once this service is imported this renders the cds-typer unsuable, automatic type generation using the VS Code plugin always crashes.
Cheers,
Geert-Jan
cds-typer not to crash and generate the types successfully.
Described in current behavior
OS: Windows 11 Pro
Node.js: v20.10.0
CDS versions:
@cap-js/cds-typer: 0.15.0
@cap-js/cds-types: 0.1.0
@cap-js/sqlite: 1.4.0
@sap/cds: 7.5.1
@sap/cds-common-content: 1.3.1
@sap/cds-compiler: 4.5.0
@sap/cds-dk: 7.5.0
@sap/cds-dk (global): 7.5.0
@sap/cds-fiori: 1.2.2
@sap/cds-foss: 5.0.0
@sap/cds-hana: 2.0.0
@sap/cds-mtxs: 1.14.1
@sap/eslint-plugin-cds: 2.6.4
No response
No response
Hi,
In my code, anywhere that I'm using a string to retrieve an object I am getting an error. I haven't raised this as a bug, as I feel it's probably something I've done wrong, but any help would be appreciated. The only thing that makes me think it might a bug and/or missing functionality is that it's happening to all of my entities where I'm doing, rather than just one.
Thanks in advance
John
Example code:
const result = (await this.getExample1(regNo)) as Example1;
const value = result[endpoint.path]; //endpoint.path is a string
Error received:
Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'Example1'.
No index signature with a parameter of type 'string' was found on type 'Example1'.
CDS of Example1
from schema
entity Example1s {
key ID : String(10);
example2 : Decimal;
example3 : Decimal;
}
Type of Example1
export function _Example1Aspect<TBase extends new (...args: any[]) => object>(Base: TBase) {
return class Example1 extends Base {
ID?: string;
example2?: number;
example3?: number;
};
}
export class Example1 extends _Example1Aspect(__.Entity) {}
export class Example1s extends Array<Example1> {}
TypeScript
Action definition:
action generateDocument(templateId : String, documentContext : String) returns @Core.MediaType: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' LargeBinary
Generated Types:
export declare const generateDocument: { (templateId: string, documentContext: string): Buffer | string, __parameters: {templateId: string, documentContext: string}, __returns: Buffer | string };
Documentation:
https://cap.cloud.sap/docs/node.js/best-practices#custom-streaming-beta
https://nodejs.org/api/stream.html#class-streamreadable
Generated Types:
export declare const generateDocument: { (templateId: string, documentContext: string): Buffer | string | Readable, __parameters: {templateId: string, documentContext: string}, __returns: Buffer | string | Readable };
Action definition:
action generateDocument(templateId : String, documentContext : String) returns @Core.MediaType: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' LargeBinary
Try to return a Readable in the action implementation.
- **OS**: Ubuntu 22.04
- **Node**: v18.16.1
- **npm**: 9.5.1
- **cds-typer**: 0.11.1
- **cds**: 7.3.0
No response
No response
Follow-up to: #34
.drafts
should only be present in entities that can actually be draftable. Currently, entities that aren't actually draftable might end up with a .drafts
property.
.drafts
property is only exposed when the entity can actually be drafted during runtimeTypeScript
Since v0.11.0, when adding a CDS function that returns a value of an enum type, cds-typer fails when the enum is accessed not directly but through another entity. The output then contains a TypeError: n.match is not a function in /lib/util.js:70
cds-typer should not fail on the given example.
# db/stuff.cds
namespace stuff;
type Language : String enum {
DE = 'German';
EN = 'English'
}
entity Books {
title : String;
language : Language;
}
# srv/test-service.cds
using {stuff} from '../db/stuff';
service TestService {
entity AvailableBooks as projection on stuff.Books;
function readOneBook() returns {
title : stuff.Books:title;
language : stuff.Books:language; // <-- Error. Simply accessing "stuff.Language" works fine though.
}
}
cds-typer version: v0.11.1 **(does not occur on v0.10.0)**
Other versions:
@cap-js/sqlite: 1.3.1
@sap/cds: 7.3.0
@sap/cds-compiler: 4.3.0
@sap/cds-dk (global): 7.2.0
@sap/cds-fiori: 1.1.0
@sap/cds-foss: 4.0.2
@sap/cds-mtxs: 1.11.0
@sap/eslint-plugin-cds: 2.6.3
Node.js: v18.18.0
https://github.com/rgrenz/cds-typer-issue
No response
I noticed that for some of our entities no types are generated. It seems that those entities correspond to views, not to tables.
Example:
The file Cryptocurrencies.cds contains the entities
CryptocurrenciesBuiltIn
CryptocurrenciesBuiltInConfig
CryptocurrenciesCustom
Cryptocurrencies
The first three entities are "normal" HANA tables. The fourth one is a union of the first three entities, like:
entity Cryptocurrencies as
select from CryptocurrenciesCustom {
key ID,
code,
name,
...
}
union all
( select from CryptocurrenciesBuiltIn as builtIn
left outer join CryptocurrenciesBuiltInConfig as conf
on conf.Cryptocurrency.ID = builtIn.ID
{
builtIn.ID,
builtIn.code,
builtIn.name,
...
}
);
As you can see in the generated files index.js and index.ts, only types for the first three entities are created. However, we also refer in our coding to the Cryptocurrencies
entity and need also types for it. Why are these types missing?
Best regards,
Michael
i'm not allowed to create a pr and i won't fork for this :D
TypeScript
Given an action such as:
action test( @mandatory testInput : String not null enum {
anEntry;
})
Yields a type like:
export declare const test: { (testInput: test_testInput): {} | null, __parameters: {testInput: test_testInput}, __returns: {} | null };
With TypeScript complaining:
Cannot find name 'test_testInput'.ts(2304)
Exported variable 'test' has or is using private name 'test_testInput'.ts(4025)
I'd expect a correct type returned from the creation.
No response
- **OS**: MacOs
- **Node**: v20.10.0.
- **npm**:
- **cds-typer**: 0.13.0
- **cds**:7.4.2
No response
No response
TypeScript
TypeError: Cannot read properties of undefined (reading 'kind')
at Visitor.visitEntity (C:\Users\Tschirschnitz\git\issue-cds-typer\node_modules\@cap-js\cds-typer\lib\visitor.js:389:24)
at Visitor.visitDefinitions (C:\Users\Tschirschnitz\git\issue-cds-typer\node_modules\@cap-js\cds-typer\lib\visitor.js:119:22)
at new Visitor (C:\Users\Tschirschnitz\git\issue-cds-typer\node_modules\@cap-js\cds-typer\lib\visitor.js:83:14)
at compileFromCSN (C:\Users\Tschirschnitz\git\issue-cds-typer\node_modules\@cap-js\cds-typer\lib\compile.js:68:23)
at compileFromFile (C:\Users\Tschirschnitz\git\issue-cds-typer\node_modules\@cap-js\cds-typer\lib\compile.js:50:12)
Types are generated.
entity Foo : cuid {
@mandatory
name : String(80);
bars : Composition of many Bar;
}
aspect Bar : cuid {
name : String(80);
}
if you change Bar to entity
everything works fine. this was already working in cds-typer 0.10 btw.
- **OS**: WIN 11
- **Node**: v18.16.1
- **npm**: 9.5.1
- **cds-typer**: 0.11.1
- **cds**: 7.2.1
https://github.com/fabiantschirschnitz/issue_cds_typer/tree/aspect_error
No response
A violation against the OSS Rules of Play has been detected.
Rule ID: rl-assigned_teams-2
Explanation: Does it have an admin team on GitHub? No
Find more information at: https://sap.github.io/fosstars-rating-core/oss_rules_of_play_rating.html
TypeScript
Hey @daogrady,
I hope you had a great christmas and a good start into 2024!
It seems that 133273d
introduced a bug on our side starting with 0.15.0 of cds-typer. The generated typescript code is malicious, since it emits the string enum values as types that are not generated by cds-typer.
String values are emitted or just the enum type name as in 0.14.0
This is our enum type:
type LockActivityType : String(20) enum {
disconnection = 'DISCONNECTION';
// TODO add more types
reconnection = 'RECONNECTION'
}
And here we use it in an action as in-parameter:
action CreateActivity(in : $self,
@mandatory
type : db.LockActivityType,
The emitted Typescript looks following:
CreateActivity: { (type: DISCONNECTION | RECONNECTION, planedDate: string | null, autoTourAssignment: boolean | null, tourID: string | null): any, __parameters: {type: DISCONNECTION | RECONNECTION, planedDate: string | null, autoTourAssignment: boolean | null, tourID: string | null}, __returns: any }
This leads to tsc-errors, since DISCONNECTION
and RECONNECTION
are no types.
- **OS**: win11
- @sap/cds: 7.5.1
- Node.js: v18.16.1
- **cds-typer**: 0.15.0
sorry, not this time. but please let me know, if the error is till unclear :)
fyi @nlaenger
Singular/ plural are currently not properly reflected in index.js
files:
// model.cds
@singular: 'Y'
@plural: 'X'
entity Z {}
// index.js
module.exports.X = csn.Z
module.exports.Z = csn.Z
// index.js
module.exports.Y = csn.Z
module.exports.Z = csn.Z
TypeScript
Hi,
The current version of [email protected] crashes the server.
Unfortunately, the error is pretty hard to catch from where it comes from.
โ๏ธ ERROR on server start: โ๏ธ
TypeError: undefined is not iterable (cannot read property Symbol(Symbol.iterator))
... /node_modules/@sap/cds-compiler/lib/model/csnRefs.js:364:31)
.../node_modules/@sap/cds-compiler/lib/model/csnRefs.js:846:17)
.../node_modules/@sap/cds-compiler/lib/model/csnRefs.js:343:19)
....
Below you ca see the package.json that I am using
package.json
"dependencies": {
"@sap/cds": "^7.3.1",
"express": "^4.18.2"
},
"devDependencies": {
"@cap-js/cds-typer": "^0.11.1",
"@cap-js/sqlite": "^1.3.1",
"@types/node": "^20.8.8",
"typescript": "^5.2.2"
},
"scripts": {
"start": "cds-ts watch",
"build:entities": "cds-typer '*' --outputDirectory ./srv/util/entities"
}
service.ts
import cds from '@sap/cds'
// imported the Book - cds typer entity built with build:entities
import { Book } from './util/entities/CatalogService'
module.exports = class BooksService extends cds.ApplicationService {
init() {
this.after('READ', Book, (books) => {})
return super.init()
}
}
Let me know if you need further info.
Thanks,
Daniel
NodeJS server should start with [email protected]
mkdir test-cds-ts
cds test-cds-ts
cds init
npm install
npm install @sap/cds@latest express@latest
npm install --save-dev @cap-js/sqlite@latest @cap-js/cds-typer@latest typescript
tsc --init
using {
Currency,
managed,
sap,
cuid
} from '@sap/cds/common';
namespace sap.capire.bookshop;
type HelloRequest {
greeterName : String;
toName : String;
}
type HelloResponse {
greetingMessage : String;
}
type Roles : String enum {
USER;
ADMIN;
}
// **************************************************************************************************
// Catalog - Service
// **************************************************************************************************
entity Books : managed {
key ID : Integer;
title : localized String(111) @mandatory;
descr : localized String(1111);
stock : Integer;
price : Decimal;
currency : Currency;
image : LargeBinary @Core.MediaType: 'image/png';
// Associations
author : Association to Authors @mandatory;
genre : Association to Genres;
reviews : Association to many Reviews
on reviews.book = $self;
stats : Association to one BookStats
on stats.book = $self;
}
entity BookStats : managed {
key ID : Integer;
views : Integer;
averageRating : Double;
book : Association to one Books;
}
entity Authors : managed {
key ID : Integer;
name : String(111) @mandatory;
dateOfBirth : Date;
dateOfDeath : Date;
placeOfBirth : String;
placeOfDeath : String;
books : Association to many Books
on books.author = $self;
}
entity Genres : sap.common.CodeList {
key ID : Integer;
parent : Association to Genres;
children : Composition of many Genres
on children.parent = $self;
}
entity Reviews : managed {
key ID : Integer;
book : Association to Books;
reviewer : Association to Users;
rating : Integer
@assert.range: [
1,
5
];
comment : String;
}
entity BookEvents : managed, cuid {
name : String;
type : String enum {
BOOK_SIGNING;
AUTHOR_TALK;
BOOK_LUNCH
};
}
// **************************************************************************************************
// **************************************************************************************************
// Admin - Service
// **************************************************************************************************
entity Users : managed {
key ID : Integer;
username : String(255) @mandatory;
email : String(255) @mandatory;
role : Roles @mandatory;
reviews : Association to many Reviews
on reviews.reviewer = $self;
}
entity UserActivityLog : managed {
key ID : Integer;
actionType : String
}
// **************************************************************************************************
Service
using {sap.capire.bookshop as my} from '../db/schema';
service CatalogService {
entity Books as projection on my.Books;
entity Authors as projection on my.Authors
entity Reviews as projection on my.Reviews;
@odata.draft.enabled: true
entity BookEvents as projection on my.BookEvents;
entity BookStats as projection on my.BookStats actions { // Bound action / function
action GenerateReport(ID : Books:ID) returns {
book : Books:title;
stats : BookStats:views;
rating : BookStats:averageRating
};
function NotifyAuthor(ID : Authors:ID) returns Boolean;
};
// Unbound action
action submitOrder(book : Books:ID, quantity : Integer) returns {
stock : Integer
};
// Unbound function
function submitOrderFunction(book : Books:ID, quantity : Integer) returns {
stock : Integer
};
}
Service implementation
import cds from '@sap/cds'
import { Book } from './util/entities/CatalogService'
module.exports = class BooksService extends cds.ApplicationService {
init() {
// const { Books, Authors } = this.entities
this.after('READ', Book, (books) => {})
return super.init()
}
}
- **OS**: Mac os x latest
- **Node**: v20.2.0
- **npm**: 9.8.0
- **cds-typer**: 0.11.1
- **cds**: 7.3.1
| test-sap-cap-ts | <Add your repository here> |
|:---------------------- | ----------- |
| Node.js | v20.2.0 |
| @sap/cds | 7.3.1 |
| @sap/cds-compiler | 4.3.0 |
| @sap/cds-dk | 7.3.1 |
| @sap/cds-dk (global) | 7.0.1 |
| @sap/eslint-plugin-cds | 2.6.3 |
| @sap/cds-mtxs | 1.12.1 |
No response
No response
Hello,
I currently try to migrate from cds2types to cds-typer and ran into an issue and I'm not sure if it's wanted behaviour or a bug.
I try to develop an service with an action and some input data.
This is an demo CDS to illustrate the issue.
service TestService {
action sayHello(request:HelloRequest) returns HelloResponse;
type HelloRequest {
greeterName:String;
toName:String;
}
type HelloResponse {
greetingMessage:String;
}
}
Executing cds-typer with cds-typer "*" --outputDirectory @cds-models
produces
// This is an automatically generated file. Please do not change its contents manually!
export type HelloRequest = {
greeterName?: string;
toName?: string;
};
export type HelloResponse = {
greetingMessage?: string;
};
// function
export declare const sayHello: (request: HelloRequest) => HelloResponse;
We implement the service like this in Typescript according to the cds-typer documentation
import { HelloRequest, HelloResponse, sayHello } from "../@cds-models/TestService/index";
import cds from '@sap/cds';
export default class TestService extends cds.ApplicationService {
init() {
this.on(sayHello, (request) => {
console.log(request.data); // outputs: { request: { greeterName: 'asd', toName: 'qwe' } }
const greeter = request.data.greeterName; // is undefined,
// const greeter = request.data.request.greeterName; // is not allowed by typescript
const toName = request.data.toName; // is undefined
// const toName = request.data.request.toName ; // is not allowed by typescript
return {
greetingMessage : `${greeter} greets ${toName}`
};
});
return super.init();
}
}
This service returns greetingMessage : "undefined greets undefined"
, because request.data contains the request
node from the parameter list of the action. But request.data is of type HelloRequest
.
cds2types solved that issue by providing additional types like in this case ActionSayHelloParams and ActionSayHelloReturn.
ActionSayHelloParams would look like this:
export interface ActionSayHelloParams {
request: HelloRequest;
}
What are we doing wrong or is there something missing?
Edit:
Added versions:
@cap-js/cds-typer: 0.7.0
@sap/cds: 7.1.2
@sap/cds-compiler: 4.1.2
@sap/cds-dk: 7.1.1
@sap/cds-dk (global): 7.0.2
@sap/cds-fiori: 1.0.0
@sap/cds-foss: 4.0.2
@sap/cds-mtxs: 1.10.0
<@sap/eslint-plugin-cds: 2.6.3
Node.js: v18.16.1
cds-typer: 1.0.0
TypeScript
I have an entity Example1
which has an association to Example2
as shown below.
entity Example1 {
demo: String(100);
example2 : Association to Example2;
}
entity Example2 : cuid {
description : String(100);
}
In my typescript file I attempt to reference the property example2_ID
in my code as per the below, however this gets flagged as an error because the property does not exist according to the types. This is an error because this property does exist. Other key fields are brought through in other Entities, it just seems to be when CUID aspect is used that the ID field is not available in the types.
As a side point this issue didn't exist in V0.3.0 I guess because it used to extend type any rather than object and so now it is stricter?
the _ID property from CUID aspect are available on parent entities.
See description above.
- **OS**: Mac OS
- **Node**: 18
- **npm**: 10 (also 9)
- **cds-typer**: 0.7.0
- **cds**: 7.1.2
No response
No response
... as we commonly do in other repos.
Or is there any reason to choose this name?
TypeScript
Right now we're encountering runtime issues when importing specific namespaces / entities.
Given an entity such as this:
namespace com.someThing.someThingElse;
entity someElements {
key guid : String;
key someAssignment : Association to Assignments;
someStringEnum : String enum {
someEnum
};
}
Typer creates within @cds-models/com/someThing/someThingElse/index.js
something such as:
[...]
// enums
module.exports.com.someThing.someThingElse.someElements = { someEnum: "someEnum"}
Trying to import this or another element exposed in that service / namespace during runtime such as:
const { someElements } = await import('#cds-models/com/someThing/someThingElse')
An error like the following is thrown:
Exception has occurred: TypeError: Cannot read properties of undefined (reading 'someThing')
at Object.<anonymous> (.../@cds-models/com/someThing/someThingElse/index.js:13:20)
at Module._compile (node:internal/modules/cjs/loader:1376:14)
at Module.m._compile (/usr/local/lib/node_modules/ts-node/src/index.ts:1618:23)
at Module._extensions..js (node:internal/modules/cjs/loader:1435:10)
at Object.require.extensions.<computed> [as .js] (/usr/local/lib/node_modules/ts-node/src/index.ts:1621:12)
at Module.load (node:internal/modules/cjs/loader:1207:32)
at Function.Module._load (node:internal/modules/cjs/loader:1023:12)
at cjsLoader (node:internal/modules/esm/translators:345:17)
at ModuleWrap.<anonymous> (node:internal/modules/esm/translators:294:7)
at ModuleJob.run (node:internal/modules/esm/module_job:218:25)
Removing the line module.expots.com.someThing.someThingElse.someElements = { someEnum: "someEnum"}
solves the issue on the import (yet removing something manually with unknown impacts might not be optimal.
Also changing the entity definition to
namespace com.someThing.someThingElse;
entity someElements {
key guid : String;
key someAssignment : Association to Assignments;
// someStringEnum : String enum {
// someEnum
// };
}
Resolves the issue on import .
You should be able to runtime import without issues even when String Enums are available.
No response
- **OS**: MacOs
- **Node**: v20.10.0.
- **npm**:
- **cds-typer**: 0.13.0
- **cds**:7.4.2
No response
No response
TypeScript
TypeError: Cannot read properties of undefined (reading 'name')
at #getDraftable (C:\Users\Tschirschnitz\git\issue-cds-typer\node_modules\@cap-js\cds-typer\lib\csn.js:46:39)
at propagate (C:\Users\Tschirschnitz\git\issue-cds-typer\node_modules\@cap-js\cds-typer\lib\csn.js:73:58)
at #propagateProjections (C:\Users\Tschirschnitz\git\issue-cds-typer\node_modules\@cap-js\cds-typer\lib\csn.js:80:13)
at DraftUnroller.unroll (C:\Users\Tschirschnitz\git\issue-cds-typer\node_modules\@cap-js\cds-typer\lib\csn.js:118:35)
at unrollDraftability (C:\Users\Tschirschnitz\git\issue-cds-typer\node_modules\@cap-js\cds-typer\lib\csn.js:159:25)
at amendCSN (C:\Users\Tschirschnitz\git\issue-cds-typer\node_modules\@cap-js\cds-typer\lib\csn.js:263:5)
at new Visitor (C:\Users\Tschirschnitz\git\issue-cds-typer\node_modules\@cap-js\cds-typer\lib\visitor.js:63:9)
at compileFromCSN (C:\Users\Tschirschnitz\git\issue-cds-typer\node_modules\@cap-js\cds-typer\lib\compile.js:67:23)
at compileFromFile (C:\Users\Tschirschnitz\git\issue-cds-typer\node_modules\@cap-js\cds-typer\lib\compile.js:49:12)
Hey cds-typer-Team,
I encountered a strange Exception today while generating types on a quite simple model. See example and repo below. Is there something wrong with my model? cds-ts serve
works great with the example.
Kind regards, Fabian
service main_service {
entity CarsProducer as projection on db.CarsProducer;
entity CarsModels as projection on db.CarsProducer.model;
//### Basic F4
annotate CarsModels with @cds.odata.valuelist;
annotate CarsModels with @UI.Identification: [{Value: name}];
};
Just run npm run cds-typer
on the example repo, please.
- **OS**: Windows
- **Node**: v18.16.1
- **npm**: 9.5.1
- **cds-typer**: 0.10.0
- **cds**: 7.2.1
https://github.com/fabiantschirschnitz/issue_cds_typer
No response
In some places in our project we read data using a transaction with the read function. With cds-typer all properties in the response come back in capital letters. In the entity definition we use camel case and also in the generated index file camel case is used, which then leads to problems when processing the response.
Originally we had cds2types in use, here the properties of the response were - as in the definition - camel case. Is this behavior intended, that all properties of the response are in capital letters and we have to adapt the processing of the response or is there an error or can we influence the "format" of the response somehow?
Versions of CDS tools:
Version of cds-typer
: 0.5.0
TypeScript
When an entity property is defined with "localized", there is another table created that contains "locale" as additional key, the original entity key fields + all localized properties. It would be beneficial if a new class was generated that represents entries in this table as well as a new reference to this text table that can be used in CQL commands.
For inspiration, the project cds2types does generate classes for the text entities.
A new classes are generated for the text tables.
No response
- **OS**:
- **Node**:
- **npm**:
- **cds-typer**:
- **cds**:
No response
No response
cds-typer nowadays uses two flavours of CSN to operate: xtended and inferred flavour.
The inferred flavour is generally superior in our case, as it contains fields that are computed later down the pipeline, like properties from CQN selections, annotations, and so on. These are all fields we are expecting in our generated type files.
The xtended flavour on the other hand does not propagate fields from inherited entities to child entities. Consider the following CDS file:
entity A {
id : Integer;
}
entity B: A {
name: String;
}
Loading it with the inferred flavour will generate this CSN snippet:
A: {
kind: 'entity',
elements: { id: { type: 'cds.Integer' } }
},
B: {
kind: 'entity',
includes: [ 'A' ],
elements: {
id: { type: 'cds.Integer' },
name: { type: 'cds.String' }
}
}
}
which would (more or less) result in the following classes:
class A {
id: number;
}
class B extends A {
id: number; // <- duplicate!
name: string;
}
This duplicate is not present when using the xtended flavour instead.
As the compilation step is not discrete and/pure, we need to load the entire model twice. This can be a considerable hit on the execution time.
Having both flavours can also be rather confusing. We constantly need to juggle them and remember which flavour to use in which use case.
We should get rid of one of the two flavours. As inferred CSN is more complete, the xtended flavour should probably be dropped. Instead of rectifying the xtended flavour with unrolled annotations, we should aim to deduplicate properties in the inferred flavour instead.
Wait for universal CSN or modify xtended CSN even more to be closer to inferred CSN.
No response
I'm currently working on switching a project to the new typescript approach using @cap-js/typer.
Unfortunately, when using the newly generated types it looks like the namespace is missing when performing CQL queries.
I'm using the same approach as described here in the documentation.
Also mentioned in following community question: https://answers.sap.com/questions/13938363/cap-typescript.html
Versions used:
@cap-js/cds-typer: 0.5.0
@cap-js/sqlite: 1.0.1
@sap/cds: 7.1.0
@sap/cds-compiler: 4.0.2
@sap/cds-dk: 7.0.3
@sap/cds-dk (global): 7.0.3
@sap/cds-fiori: 1.0.0
@sap/cds-foss: 4.0.2
@sap/cds-mtxs: 1.9.2
@sap/eslint-plugin-cds: 2.6.3
@thevaluechain/cap-number-range: 1.1.5
Node.js: v16.19.0
home: /home/user/projects/icm-reuse-numberrange/node_modules/@sap/cds
Sample Model
using { User, cuid, managed } from '@sap/cds/common';
namespace eu.thevaluechain.common.numberrange.db;
@singular: 'NumberRangeObject'
@plural: 'NumberRangeObjects'
@assert.unique: {object: [Object]}
entity NumberRangeObjects : cuid, managed {
Object: String(10) @mandatory;
Description: String(40);
NumberLength: Decimal(2,0);
WarningPercentage: Integer;
Prefix: Boolean;
Intervals: Composition of many Intervals on Intervals.Object=$self;
}
@singular: 'Interval'
@plural: 'Intervals'
@assert.unique: {objectnumber: [Object,NumberRangeNo]}
entity Intervals : cuid, managed {
Object: Association to one NumberRangeObjects;
NumberRangeNo: UInt8 @mandatory;
Description: String(40);
NumberFrom: Integer64 @mandatory;
NumberTo: Integer64 @mandatory;
IntervalStatusses: Association to many IntervalStatusses on IntervalStatusses.Interval=$self;
}
@singular: 'IntervalStatus'
@plural: 'IntervalStatusses'
@assert.unique: {intervalprefix: [Interval,Prefix]}
entity IntervalStatusses : cuid, managed {
Interval: Association to one Intervals;
Prefix: String(4) @readonly;
NumberStatus: Integer64 @readonly @Core.Immutable;
}
Sample Code
const {NumberRangeObject, Intervals} = require('../../@cds-models/eu/thevaluechain/common/numberrange/db')
// Get number range object configuration
this._numberRangeObject = await SELECT.one.from(NumberRangeObject).where({ID: this._numberRangeObjectID});
if(!this._numberRangeObject){
throw new Error("Number Range Object not found!");
}
this._numberRangeObject.Intervals = await SELECT.from(Intervals).where({Object_ID: this._numberRangeObjectID });
TypeScript
When the project path contains spaces in Windows it crashes the type generation.
Sample logs shared below:
Node.js v20.9.0
CDSError: Could not (re)generate types for model. Could not read file content of *: Failed: node C:\Users\<i-number>\foo bar\project\node_modules\@cap-js\cds-typer\lib\cli.js "*" --outputDirectory "C:\Users\<i-number>\foo bar\project\@cds-models"
<exit code:>
1
<stderr:>
node:internal/modules/cjs/loader:1051
throw err;
^
Error: Cannot find module 'C:\Users\<i-number>\foo'
at Module._resolveFilename (node:internal/modules/cjs/loader:1048:15)
at Module._load (node:internal/modules/cjs/loader:901:27)
at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:83:12)
at node:internal/main/run_main_module:23:47 {
code: 'MODULE_NOT_FOUND',
requireStack: []
}
Type generation should work as expected.
- **OS**: Windows
- **Node**:
- **npm**:
- **cds-typer**: 0.15.0
- **cds**:
No response
No response
TypeScript
I'm getting the following error while starting the CAP application whenever I reference enums in the same way as it is explained in the documentation.
โ๏ธ ERROR on server start: โ๏ธ
@cds-models/db/index.js:9:102 - error TS2339: Property 'enum' does not exist on type 'LinkedDefinition'.
9 module.exports.SampleEnum = Object.fromEntries(Object.entries(cds.model.definitions['db.SampleEnum'].enum).map(([k,v]) => [k,v.val??k]))
~~~~
I should be able to reference enum values using the const
that is generated by cds-typer without any error.
.cds
file:namespace db;
type SampleEnum : String(3) enum {
a = 'AAA';
b = 'BBB';
}
.ts
file (there is no compiler error at this step):import { SampleEnum } from "#cds-models/db";
...
someVariable === SampleEnum.a;
cds-ts watch
- **OS**: Linux distro of SAP BAS (5.15.114-gardenlinux-cloud-amd64)
- **Node**: 18.14.2
- **npm**: 9.5.0
- **cds-typer**: 0.12.0
- **cds**: 7.4.2
https://github.com/lorenzofratus/cds-typer-enum-bug
Please let me know if I'm missing some configuration or if I can provide more information.
JavaScript, TypeScript
Currently, when I extend an external service with a custom association, it is not included in the .d.ts files generated by cds-typer. It seems that the select on the projection is not even taken into account by cds-typer.
I expect that when I either restrict a service projection with a select or extend it with new fields/expands, it should be considered by cds-typer.
One can reproduce the behaviour with the ext-service-consume-ui
branch in the Risk Management Sample:
git clone --branch ext-service-consume-ui https://github.com/SAP-samples/cloud-cap-risk-management.git
cd cloud-cap-risk-management
cds add typer
npm i
entity Suppliers as projection on bupa.A_BusinessPartner {
key BusinessPartner as ID,
BusinessPartnerFullName as fullName,
BusinessPartnerIsBlocked as isBlocked,
+ to_Risks : Association to many Risks on to_Risks.supplier = $self
}
npx @cap-js/cds-typer '*' --outputDirectory @cds-models
export function _SupplierAspect<TBase extends new (...args: any[]) => object>(Base: TBase) {
return class Supplier extends Base {
/**
* Key identifying a business partner in the SAP system. The key is unique within a client.
*/
BusinessPartner?: string;
/**
* Gives an alphanumeric key, which clearly identifies the customer or vendor in the SAP system.
*/
Customer?: string;
/**
* Specifies an alphanumeric key that uniquely identifies the supplier in the SAP system.
*/
Supplier?: string;
/**
* Key for academic title.
*
* You can define a key for an academic title in Customizing.
*/
AcademicTitle?: string;
/**
* You can use authorization groups to stipulate which business partners a user is allowed to process.
*
* Use the following authorization object:'Business partners: authorization groups' (B_BUPA_GRP).The system only checks this authorization if you made an entry in the "Authorization group" field for the business partner. Otherwise, any user may process the business partner.
*/
AuthorizationGroup?: string;
/**
* Category under which a business partner is classified.
*
* You can distinguish between the following business partner categories:OrganizationNatural personGroup of natural persons or organizationsThe processing screens for the business partner categories are set up differently.So, for example, the screen for an organization contains the field Legal form, but this is not needed in the screen for a natural person.
*/
BusinessPartnerCategory?: string;
BusinessPartnerFullName?: string;
/**
* Classification assigned when creating a business partner.
*
* Assign each business partner to a grouping when you create the business partner. The grouping determines the number range. You cannot change the assignment afterwards.You can define the groupings, their descriptions, the associated number range and other attributes in Customizing.You can define standard groupings for the internal and the external number assignment.For each grouping create a number range.When you create a business partner, the entry in the grouping field determines whether and how an entry is made in the business partner number field.
*/
BusinessPartnerGrouping?: string;
BusinessPartnerName?: string;
BusinessPartnerUUID?: string;
/**
* Correspondence language (written) for business partners in the 'Person' category. Maintain the correspondence language for business partners in the 'Organization' and 'Group' category with the address (communication).
*
* When transferring data (direct input), make sure that for a'Person', the field 'LANGU_CORR' and for an'Organization' or "Group" the field 'LANGU'has an entry.
*/
CorrespondenceLanguage?: string;
CreatedByUser?: string;
CreationDate?: string;
CreationTime?: string;
FirstName?: string;
/**
* Key for form of address text.
*
* You can also define a form of address text in Customizing.The form of address text can be maintained in different languages.
*/
FormOfAddress?: string;
/**
* An industry sector is the term used to classify a company according to its main business activity.
*
* You can assign an industry sector to business partners in the category 'Organization'RetailBanksServicesIndustryHealth servicePublic sectorMedia
*/
Industry?: string;
/**
* Here you enter the first 7 digits of the international location number.
*
* The International Location Number (ILN) is assigned (in Germany by the Centrale for Coorganisation GmbH)) when a company is founded. It consists of 13 digits, the last digit being the check digit. There are two categories of location numbers:Participants who only need an ILN to cleary and unmistakably identify themselves for communication with the business partner are given a category 1 ILN. This cannot be used to identify articles by means of EAN.Participants who wish to assign the location numbers for their own enterprise areas are given a category 2 ILN. For a category 2 ILN, digits 1 to 7 are described as basis number. This is used as basis for the creation of article numbers (EAN).
*/
InternationalLocationNumber1?: string;
/**
* Here, you enter digits 8-12 of the 13-digit international location number.
*
* The international location number (ILN) is assigned when establishing a company (by the "Zentrale fรผr Coorganisation GmbH" in Germany). It consists of 13 digits, the last of which is the check digit. There are two types of international location numbers:Subscribers who only need one ILN to identify themselves in communication with the business partner are given an ILN of type 1. These cannot be used for identifying articles by means of EAN.Subscribers who need to assign location numbers for their own company areas are given an ILN of type 2. Positions 1 through 7 of the ILN type 2 are known as the basis number. This basis number forms the basis for article numbers (EAN).
*/
InternationalLocationNumber2?: string;
IsFemale?: boolean;
IsMale?: boolean;
/**
* Indicator through which a distinction between natural and legal persons can be made during tax reporting.
*
* Is used in Italy and Mexico ,among other countries.Brasil: If the indicator is not set, 'CGC' is relevant in tax number 1. If the indicator is set, 'CPF' is relevant in tax number 2.Colombia: In the case of some natural persons, the NIT number does not have a check digit. In this case you should set this indicator and the check is deactivated.
*/
IsNaturalPerson?: string;
IsSexUnknown?: boolean;
GenderCodeName?: string;
/**
* Language for verbal communication with a business partner.
*
* This language may differ from the language(s) defined for written correspondence.
*/
Language?: string;
LastChangeDate?: string;
LastChangeTime?: string;
LastChangedByUser?: string;
LastName?: string;
/**
* Denotes certain legal norms that are of significance for the organization of a company.
*
* For business partners in the category "Organization", you can state the legal form of the company. This is for information purposes only.Stock corporation (AG in Germany)Limited liability company (GmbH in Germany)
*/
LegalForm?: string;
/**
* First name field for business partners in the Organization category.
*/
OrganizationBPName1?: string;
/**
* Second name field for business partners in the Organization category.
*/
OrganizationBPName2?: string;
/**
* Third name field for business partners in the Organization category.
*/
OrganizationBPName3?: string;
/**
* Fourth name field for business partners in the Organization category.
*/
OrganizationBPName4?: string;
/**
* Indicates the official registration of a company in the Commercial Register.
*
* If a company is not officially registered in the Commercial Register, it has to use some type of text addition, such as foundation pending, when referring to the legal form.
*/
OrganizationFoundationDate?: string;
/**
* Term for the end of bankruptcy proceedings.
*
* This date also indicates that the company no longer exists.
*/
OrganizationLiquidationDate?: string;
/**
* Denotes the term that you define for a business partner, and via which you can restrict the search for a business partner in the business partner search or in the locator.
*/
SearchTerm1?: string;
/**
* Denotes the term that you define for a business partner, and via which you can restrict the search for a business partner in the business partner search or in the locator.
*/
SearchTerm2?: string;
AdditionalLastName?: string;
BirthDate?: string;
/**
* If the Business partner's actual birthdate is unknown, a partial entry can be made or read. This field then indicates which part of the birthdate is unknown. Below are some examples (Dates are specified in format MM/DD/YYYY):
*
* 01/01/0000 => 01/01/1880 Year unknown00/01/1911 => 01/01/1911 Month unknown05/00/1911 => 05/01/1911 Day unknown05/05/1911 => 05/05/1911 Fully known00/00/1911 => 05/05/1911 Day & Month unknown00/05/0000 => 05/05/1911 Month & Year unknown05/00/0000 => 05/05/1911 Day & Year unknown00/00/0000=> 05/05/1911 Fully unknown'Date of Birth: Status' field determines the unknown parts of birthdate.Enter a valid date under Birthdate. Future dates are not accepted. If any part/s of the date is/are unknown, select the nearest date.If year is unknown, select any random valid year.
*/
BusinessPartnerBirthDateStatus?: string;
BusinessPartnerBirthplaceName?: string;
BusinessPartnerDeathDate?: string;
/**
* If the business partner is blocked centrally, certain activities cannot be executed.
*/
BusinessPartnerIsBlocked?: boolean;
/**
* You can use the business partner type to group business partners according to your own criteria in Customizing (IMG).
*
* In Customizing you can show or hide fields for data entry, depending on the requirements of the relevant business partner type.Select a business partner type. You can obtain help by pressing the F4 key.
*/
BusinessPartnerType?: string;
ETag?: string;
/**
* First name field for business partners in the Group category.
*/
GroupBusinessPartnerName1?: string;
/**
* Second name field for business partners in the Group category.
*/
GroupBusinessPartnerName2?: string;
/**
* Internal key for identifying the address for communication data that spans all addresses in Business Partner.
*
* For more information on the significance and usage of the address number, see the documentation for Business Address Services (BAS).
*/
IndependentAddressID?: string;
/**
* The check digit is derived from a special check digit procedure from digits of the previous international location numbers. In this way, you can check whether the ILN entered is actually valid.
*/
InternationalLocationNumber3?: string;
MiddleName?: string;
/**
* The country/region for the name format rule and the name format rule key together uniquely identify a formatting rule.
*
* A country/region can have several formats which correspond to different rules. You need formatting rules to describe the composition of a person's name.
*/
NameCountry?: string;
/**
* See Name format.
*/
NameFormat?: string;
/**
* States the complete name of a person.
*
* The complete name is generally generated and saved by the Business Address Services (BAS) according to country-specific rules from the individual name components (without the form of address).If, during the formatting of an address, you want to use an alternative name, you can manually format the alternative name here.
*/
PersonFullName?: string;
/**
* Internal key for identifying a person in Business Address Services.
*
* For more information about the meaning and use of the person number and Business Address Services concepts, see the function group SZA0 documentation.
*/
PersonNumber?: string;
/**
* Establishes if the business partner is meant to be archived.
*
* If the indicator is set, the relevant business partner can be archived from the view of the business partner administration.If the check of the data to be archived shows, for example, that there are still active business transactions the archiving of the business partner data is prevented even if the indicator is set.If the indicator is not set, the business partner will not be taken into consideration during archiving.
*/
IsMarkedForArchiving?: boolean;
/**
* Business partner number from an external system or a legacy system.
*
* If the current business partner is known under a different number in an external system, you can store this number here for information purposes.Direct input gives you the option of maintaining a business partner by specifying the external business partner number. If you maintain business partner data in your legacy system, you can transmit changes made to business partners to the SAP system without having to know the SAP business partner number in the legacy system.
*/
BusinessPartnerIDByExtSystem?: string;
/**
* Company ID standard for the whole group.
*/
TradingPartner?: string;
/**
* Please add an ON condition
*/
to_BuPaIdentification?: __.Association.to.many<_API_BUSINESS_PARTNER.A_BuPaIdentification_>;
/**
* Key identifying a business partner in the SAP system. The key is unique within a client.
*/
to_BuPaIdentification_BusinessPartner?: string;
/**
* A document (such as an ID card or driver's license) or an entry in a system of records (such as a commercial register) whose key can be stored as an attribute for a business partner.
*
* The identification type is for classifying identification numbers.You can define the identification types and their descriptions in Customizing.You can also specify for which business partner category an ID type should be valid.If necessary, assign the identification type to an Identification Category.You can only assign one identification type to an identification category.
*/
to_BuPaIdentification_BPIdentificationType?: string;
/**
* Number that serves to identify a business partner, such as driver's license, or ID card number.
*/
to_BuPaIdentification_BPIdentificationNumber?: string;
/**
* Please add an ON condition
*/
to_BuPaIndustry?: __.Association.to.many<_API_BUSINESS_PARTNER.A_BuPaIndustry_>;
/**
* Describes an industry.
*
* An industry is a classification of companies according to their main business activity. For example, you can use Commerce, Banking, Services, Industry, Healthcare, Public Sector, Media, and so on, as industries.You can define industries along with their descriptions in Customizing.Assign the industry key to an industry key system.
*/
to_BuPaIndustry_IndustrySector?: string;
/**
* Serves to combine and categorize several industries into a group.
*
* You can create different industry systems, each with its own catalog of industries, whereby an industry can be assigned to several industry systems.You have to select one industry system as the standard industry system. This is then automatically displayed in the initial screen for the maintenance of industry data.You can define an industry system along with its description in Customizing. You can assign several industry systems to a business partner.If you choose the button All Industry Systems, you can access all the industry systems defined in the Customizing using the input help.
*/
to_BuPaIndustry_IndustrySystemType?: string;
/**
* Key identifying a business partner in the SAP system. The key is unique within a client.
*/
to_BuPaIndustry_BusinessPartner?: string;
/**
* Please add an ON condition
*/
to_BusinessPartnerAddress?: __.Association.to.many<_API_BUSINESS_PARTNER.A_BusinessPartnerAddress_>;
/**
* Key identifying a business partner in the SAP system. The key is unique within a client.
*/
to_BusinessPartnerAddress_BusinessPartner?: string;
/**
* Internal key for identifying a Business Address Services address.
*
* For more information about the meaning and use of the address number and the Business Address Services concepts, see the function group SZA0 documentation.
*/
to_BusinessPartnerAddress_AddressID?: string;
/**
* Please add an ON condition
*/
to_BusinessPartnerBank?: __.Association.to.many<_API_BUSINESS_PARTNER.A_BusinessPartnerBank_>;
/**
* Key identifying a business partner in the SAP system. The key is unique within a client.
*/
to_BusinessPartnerBank_BusinessPartner?: string;
/**
* Key identifying a business partner's bank details.
*
* Enter a bank details ID for each separate set of bank details for a business partner.Business Partner: H. MillerBD-ID Fin.institution Acct no. 0001 Chemical Bank, NYC 56234560002 Chemical Bank, NYC 56231220003 First Bank of Pittsburgh ...Business partner: T.Wolsey and Co.BD-ID Fin.institution Acct no.GIR0 Citibank, Charleston ...GIR1 Chemical Bank, NYC ...
*/
to_BusinessPartnerBank_BankIdentification?: string;
/**
* Please add an ON condition
*/
to_BusinessPartnerContact?: __.Association.to.many<_API_BUSINESS_PARTNER.A_BusinessPartnerContact_>;
/**
* The business partner relationship number is an internal number that identifies the business partner relationship set.
*/
to_BusinessPartnerContact_RelationshipNumber?: string;
/**
* Key identifying a business partner in the SAP system. The key is unique within a client.
*/
to_BusinessPartnerContact_BusinessPartnerCompany?: string;
/**
* Key identifying a business partner in the SAP system. The key is unique within a client.
*/
to_BusinessPartnerContact_BusinessPartnerPerson?: string;
to_BusinessPartnerContact_ValidityEndDate?: string;
/**
* Please add an ON condition
*/
to_BusinessPartnerRole?: __.Association.to.many<_API_BUSINESS_PARTNER.A_BusinessPartnerRole_>;
/**
* Key identifying a business partner in the SAP system. The key is unique within a client.
*/
to_BusinessPartnerRole_BusinessPartner?: string;
/**
* Function that a business partner takes on, depending on a business transaction.
*
* You can define business partner roles along with their attributes in Customizing.You can create an alphanumeric, 6-digit key for the BP role. You can also choose a title as the short form and a description as the long form for the role text.Screen control in the dialog takes place by assigning a BP view.A program can access specific business partner roles for a business partner using thebusiness partner role category . The role categories are also in the TB003 table.
*/
to_BusinessPartnerRole_BusinessPartnerRole?: string;
/**
* Please add an ON condition
*/
to_BusinessPartnerTax?: __.Association.to.many<_API_BUSINESS_PARTNER.A_BusinessPartnerTaxNumber_>;
/**
* Key identifying a business partner in the SAP system. The key is unique within a client.
*/
to_BusinessPartnerTax_BusinessPartner?: string;
/**
* Specifies the tax number category.
*/
to_BusinessPartnerTax_BPTaxType?: string;
/**
* Please add an ON condition
*/
to_Customer?: __.Association.to<_API_BUSINESS_PARTNER.A_Customer>;
/**
* Gives an alphanumeric key, which clearly identifies the customer or vendor in the SAP system.
*/
to_Customer_Customer?: string;
/**
* Please add an ON condition
*/
to_Supplier?: __.Association.to<_API_BUSINESS_PARTNER.A_Supplier>;
/**
* Specifies an alphanumeric key that uniquely identifies the supplier in the SAP system.
*/
to_Supplier_Supplier?: string;
static actions: {
}
};
}
export class Supplier extends _SupplierAspect(__.Entity) {}
- **OS**:
- **Node**: v18.18.0
- **npm**: 9.8.1
- **cds-typer**: 0.11.1
- **cds**: 6.8.4
No response
No response
TypeScript
When defining an enum type that is then not used anywhere in CDS (but possibly used in TS), an appropriate type is generated by cds-typer but the app then crashes on startup.
cds-ts watch
...
TypeError: Cannot read properties of undefined (reading 'enum')
The app should not crash on startup.
// stuff.cds
namespace stuff;
type Language : String enum {
DE = 'German';
EN = 'English'
}
// do not use Language in any entity or service definition
// test-service.ts
import { Language } from "#cds-models/stuff"; // TypeError: Cannot read properties of undefined (reading 'enum')
console.log(Language);
@cap-js/cds-typer: 0.11.1
| Node.js | v18.18.0 |
| @sap/cds | 7.3.0 |
| @sap/cds-compiler | 4.3.0 |
| @sap/cds-dk | -- missing |
| @sap/cds-dk (global) | 7.2.0 |
| @sap/eslint-plugin-cds | 2.6.3 |
| @sap/cds-mtxs | 1.11.0 |
https://github.com/rgrenz/cds-typer-issue/tree/unused-enum-generation
This might be an upstream issue/feature where @sap/cds "optimizes" the source and throws away any types that are unused in CDS. A workaround is to define a dummy entity where the enum is used (see example repo).
We are currently only checking the generated index.ts
files as part of our tests. The JS files seemed trivial and our main focus are the types anyway, so checking the JS files didn't seem like it was worth the overhead.
But as #53 proved, we should probably have tests for those files as well.
I have problems to integrate cds-typer in our CI process. I already had a look at the documentation and I also tried to adapt the mta.yaml file. However, I always get an error like
Error: lib/masterData/businessPartners/DbBusinessPartnerRepository.ts(17,38): error TS2307: Cannot find module '#cds-models/sap/erp4sme/c4b/masterData/businessPartners' or its corresponding type declarations.
in the build process of the pipeline.
The build job on github is defined in our pr_voter.yml file. Here, npm run build
is executed.
Thus, I added to the build script in the package.json the script:
"cds-typer": "npx @cap-js/cds-typer \"*\" --outputDirectory @cds-models && npx @cap-js/cds-typer \"*\" --outputDirectory gen/srv/@cds-models",
I tried several options and finally decided to run cds-typer twice, once with the output directory @cds-models
and once with gen/srv/@cds-models
. But the result is always the same: the error mentioned above.
E.g. the generated types cannot be found in the file DbBusinessPartnerRepository.ts.
Locally in Visual Studio Code, everything works fine.
It would be great if you can have a look at our repository and the PR error and give some advice. If needed, we can schedule a meeting.
Thanks and best regards,
Michael
Support for Node 16 will soon run out: https://nodejs.dev/en/about/releases/
Adjust CI matrix to run tests on node.js 18 and 20 instead.
TypeScript
Example:
namespace sap.testmodels;
entity TestObjects {
key ID: UUID;
name: String not null;
description: String;
dependencies: Association to many ...;
...
}
using sap.testmodels as db from '../db';
service TestService {
entity TestObjects as projection on db.TestObjects excluding { dependencies };
}
The CDS entities above are compiled to
class TestObjects {
ID: string;
name: string;
description: string | null;
dependencies: Association.to.many<...>;
}
Compiled TypeScript models should leave out properties which are marked as excluded on CDS layer.
class TestObjects {
ID: string;
name: string;
description: string | null;
}
No response
- **OS**: MacOS 14.1.1
- **Node**: 18.18.2
- **npm**: 9.8.1
- **cds-typer**: 0.12.0
- **cds**: 7.3.1
No response
Absolutely the same result if to use explicit select of certain properties. For example:
using sap.testmodels as db from '../db';
service TestService {
entity TestObjects as projection on db.TestObjects { ID, name, description as desc };
}
Hi,
I am testing a project developed using TS and cds-typer.
Currently, the cds-typer produces TS & JS files and somehow jest doesn't like something in the JS files.
Do you know how we can test CDS-typer generated entities with Jest on TS projects?
Currently on SAP CAP cds.test docu, I was not able to find something useful for test cds-typer with TS>
โ Test suite failed to run
TypeError: cds.entities is not a function
1 | // This is an automatically generated file. Please do not change its contents manually!
2 | const cds = require('@sap/cds')
> 3 | const csn = cds.entities('CatalogService')
| ^
4 | module.exports = { name: 'CatalogService' }
5 | module.exports.BookEvent = csn.BookEvents
6 | module.exports.BookEvents = csn.BookEvents
cds-typer version : 0.11.1
npm : 9.8.0
node : 21.1.0
OS : Macosx
let me know if you need further info
TypeScript
Currently it seems like types for CDS models from separate node modules that are using namespaces get wrongly generated.
The import is generated as follows: import * as _ from ...
The types used seem to be missing the namespace prefix as seen in below example:
Fixing this manually as below, solves the issue:
Generated types should include the prefix as generated in the import
No response
OS: Business Application Studio
CDS versions:
@cap-js/cds-typer: 0.11.1
@cap-js/db-service: 1.3.2
@cap-js/sqlite: 1.3.1
@sap/cds: 7.3.1
@sap/cds-common-content: 1.2.0
@sap/cds-compiler: 4.3.2
@sap/cds-dk: 7.3.1
@sap/cds-dk (global): 7.3.1
@sap/cds-fiori: 1.1.0
@sap/cds-foss: 4.0.2
@sap/cds-hana: 2.0.0
@sap/cds-mtxs: 1.12.1
@sap/eslint-plugin-cds: 2.6.3
Node.js: v18.14.2
No response
No response
TypeScript
If you have type aliasing definitions in your cds schema like the following:
entity Countries {
key code : String(2);
name : String(255);
}
type Country : Association to Countries;
cds-typer
will generate duplicate definitions:
export type Country = __.Association.to<Country>;
export function _CountryAspect<TBase extends new (...args: any[]) => object>(Base: TBase) {
return class Country extends Base {
code?: string | null;
name?: string | null;
static actions: {
}
};
}
export class Country extends _CountryAspect(__.Entity) {}
Country
here is defined both as a type
and a class
:
export type Country = __.Association.to<Country>;
export class Country extends _CountryAspect(__.Entity) {}
This obviously causes TypeScript errors:
index.ts:4:13 - error TS2300: Duplicate identifier 'Country'.
4 export type Country = __.Association.to<Country>;
No response
Generate definitions for the following cds schema and then try to use it in your TS code:
entity Countries {
key code : String(2);
name : String(255);
}
type Country : Association to Countries;
- **OS**: Windows 10
- **Node**: 18.17.1
- **yarn**: 4.0.2
- **cds-typer**: 0.15.0
- **cds**: 7.5.1
No response
No response
Hello,
When the aspect elements are used in event parameters , @cds-models/index.ts file contains the following error.
export type [object Object] = {};
db/schema.cds ( the cuid aspect is used)
using {
Currency,
managed,
cuid,
sap
} from '@sap/cds/common';
namespace sap.capire.bookshop;
entity Books : cuid, managed {
@mandatory title : localized String(111);
descr : localized String(1111);
@mandatory author : Association to Authors;
genre : Association to Genres;
stock : Integer;
price : Decimal;
currency : Currency;
image : LargeBinary @Core.MediaType: 'image/png';
}
In CatalogService cds file, OrderedBook event parameter book referenced from Book:ID .
using { sap.capire.bookshop as my } from '../db/schema';
service CatalogService {
/** For display in details pages */
@readonly entity Books as projection on my.Books { *,
author.name as author
} excluding { createdBy, modifiedBy };
event OrderedBook : { book: Books:ID; quantity: Integer; buyer: String };
}
Regards.
ilhan Burak
Hi,
I noticed that the type checking is not working as one would expect.
The compiler correctly remarks upon false method calls (e.g. calling startsWith
on a generated Date
-type property):
However, if I try to access a property that does not exist at all, I do not get a syntax error, only the information that an any
-typed property is accessed:
I had a look into the generated .ts
files and discovered that by changing the aspect-functions so that the return type is object
instead of any
, the expected syntax errors appear. (Note: This needs to be done for all aspect functions involved in the used type. This can be seen in commit stockbal/cap-samples@da6ac60)
...
// currently generated -> no syntax error
// export function _BookAspect<TBase extends new (...args: any[]) => any>(Base: TBase) {
// correct syntax error is displayed
export function _BookAspect<TBase extends new (...args: any[]) => object>(Base: TBase) {
return class Book extends Base {
ID ?: number;
title ?: string;
stock ?: number;
publishedOn ?: Date;
};
}
...
I am not sure if this would cause problems in other situations or not. Another option would be usage of infer
, but unfortunately I am no TypeScript wizard to provide a solution there.
It could also be a misconfiguration in my tsconfig.json
. ๐
Please have a look.
Thanks and regards,
Ludwig
TypeScript
When the projects get build and run in production, the ENUM values are all undefined.
this seems to be an issue with the generation of the enum in the index.js of the by cds-typer generated code
The ENUM should be populated
npm run start
and inspect the value if a
in the test-service.ts
- **OS**: Ubuntu
- **Node**: 18.18.0
- **npm**: 9.8.1
- **cds-typer**: 0.11.1
- **cds**:
|:---------------------- | ----------- |
| Node.js | v18.18.0 |
| @sap/cds | 7.2.0 |
| @sap/cds-compiler | 4.2.2 |
| @sap/cds-dk | 7.2.0 |
| @sap/cds-dk (global) | 7.2.0 |
| @sap/eslint-plugin-cds | 2.6.3 |
| @sap/cds-mtxs | 1.11.0 |
https://github.com/sebbi08/cds-typer-issue/tree/bug-enum
No response
Hi,
the following CDS generates a incomplete result:
type A {
b : B;
bs : many B;
}
type B {
prop1 : String;
prop2 : String;
}
=>
// This is an automatically generated file. Please do not change its contents manually!
export type A = {
b ?: B;
bs ?: Array<{}>; //ISSUE
};
export type B = {
prop1 ?: string;
prop2 ?: string;
};
I would expect the following
export type A = {
b ?: B;
bs ?: Array<B>; //EXPECTED
};
export type B = {
prop1 ?: string;
prop2 ?: string;
};
Best regards
Daniel
When using the CDS-Typer tool to generate TypeScript types for SAP CAP CDS services, it's observed that the tool does not explicitly differentiate between fields that can be null and those that can't. This becomes particularly problematic when TypeScript's exactOptionalPropertyTypes is enabled.
Both the following CDS definitions for getUserDetails() yield the TypeScript type example?: string;
, even though one specifies nullability:
function getExample() returns {
[...]
example : String;
[...]
};
function getExample() returns {
[...]
example : String null;
[...]
};
The type generation should be more specific. For instance, a more explicit type definition like example?: string | null
; would be more informative and compatible with exactOptionalPropertyTypes.
Note
I'm uncertain on the handling of undefined properties. It might also make sense to check whether example?: string | undefined
is an option for the first, example?: string | undefined | null
for the second case.
TypeScript
Given an entity with delimited identifier syntax:
entity Something : cuid {
icon : String @assert.range enum {
![sap-icon://pharmacy];
![sap-icon://message-success];
};
}
The types generated are missing the potentially needed quotation marks:
const Something_Icon = {
sap-icon://pharmacy: "sap-icon://pharmacy",
sap-icon://message-success: "sap-icon://message-success",
} as const
Leading to the generated code containing errors.
I would have expected the properties to be quoted:
const Something_Icon = {
"sap-icon://pharmacy": "sap-icon://pharmacy",
"sap-icon://message-success": "sap-icon://message-success",
} as const
See data above.
- **OS**: Mac OS
- **Node**: v20.10.0
- **npm**: 10.2.3
- **cds-typer**: 0.12.0
- **cds**: 7.4.1
No response
No response
Hi,
Currently it is not possible to use the generated types to register handlers specific to draft entities.
Let's say we have following service file:
using my.bookshop as my from '../db/data-model';
service CatalogService {
@odata.draft.enabled
entity Books as projection on my.Books;
}
In the service handler file I would just like to use the following approach to register my handler for the draft entity Books
.
import { ApplicationService } from "@sap/cds";
import { Books } from "#cds-models/CatalogService";
export class CatalogService extends ApplicationService {
override async init(): Promise<void> {
this.after("READ", Books.drafts, (books) => {
// ...
});
await super.init();
}
}
Enhance the generated types for draft enabled service entities in the following way:
import { Definition } from '@sap/cds/apis/reflect';
...
export class Book extends _._managedAspect(_._cuidAspect(_BookAspect(__.Entity))) {
static drafts: Definition
}
export class Books extends Array<Book> {
static drafts: Definition;
}
This would solve the missing drafts
property and would allow the handler registration. You would not get type inference in the data
property unfortunately and a cast would be necessary.
this.after("READ", Books.drafts, (books: Books) => { });
I am not sure if both features can be realized at once. But I personally could live with the cast ๐.
Regards,
Ludwig
Versions of CDS tools[^3]:
cap-type-generator | |
---|---|
Node.js | v18.17.0 |
@sap/cds | 7.0.3 |
@sap/cds-compiler | 4.0.2 |
@sap/cds-dk | -- missing |
@sap/cds-dk (global) | 7.0.3 |
@sap/eslint-plugin-cds | 2.6.3 |
@sap/cds-mtxs | 1.9.2 |
Version of cds-typer
[^1]: 0.5.0
Hi,
I saw cds-typer at this years reCAP and wanted to give it a try in one of my CAP Typescript projects.
I followed the steps mentioned in the quickstart and was able to install cds-typer, but to me it seems it doesn't work correctly.
I'm having the following difficulties:
.cds
file doesn't autogenerate the types for me.any
.import { ... } from 'path'
and move that to the top of my service implementations file, the variables are typed as class
, but they don't work at runtime.Additionally I had to tinker with some esilnt rules like (no-var-requires), to make my service syntactically correct, as well as add @cds-models to the eslint ignore list, but these shouldn't be causing above mentioned problems.
Is there anything obvious that I'm overlooking or not doing right?
Below are snippets of my tsconfig.json
and package.json
files, in case they might help:
{
"compilerOptions": {
"target": "ES2022",
"module": "CommonJS",
"moduleResolution": "node",
"skipLibCheck": true,
"preserveConstEnums": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"allowUnreachableCode": false,
"allowUnusedLabels": false,
"noFallthroughCasesInSwitch": true,
"noImplicitOverride": true,
"noImplicitReturns": true,
"noUncheckedIndexedAccess": true,
"noPropertyAccessFromIndexSignature": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"exactOptionalPropertyTypes": true,
"inlineSourceMap": true,
"allowJs": false,
"strict": true,
"strictPropertyInitialization": false,
"strictNullChecks": true,
"forceConsistentCasingInFileNames": true,
"paths": {
"#cds-models/*": ["./@cds-models/*/index.ts"]
},
"rootDirs": ["./", "./@cds-models"]
}
}
{
"name": "...",
"version": "1.0.0",
"description": "...",
"private": true,
"scripts": {
...
},
"dependencies": {
"@sap-cloud-sdk/http-client": "^3.4.0",
"@sap-cloud-sdk/util": "^3.4.0",
"@sap/cds": "^7.1.1",
"@sap/xssec": "^3.3.3",
"express": "^4.18.2",
"passport": "^0.6.0"
},
"devDependencies": {
...
"@typescript-eslint/eslint-plugin": "^5.62.0",
"@typescript-eslint/parser": "^5.62.0",
...
"eslint": "^8.47.0",
...
"typescript": "^5.1.6",
"@cap-js/cds-typer": "^0.6.1"
},
"imports": {
"#cds-models/*": "./@cds-models/*/index.ts"
}
}
Thanks in advance for any help
Best regards
TypeScript
We're in the process of migrating our existing types generated with version 0.5.0 to the new typer functionality. Since this update types have become more strict which now seems to be causing issues when trying to work with drafts entities. (e.g. inserting additional draft data through code)
Each draft entity has four fields for draft management:
Currently it seems like these fields are not covered by the typer functionality.
Having these administrative fields available, so we can access the draft_uuid to e.g. add additional entities to a composition through code.
No response
OS: Business application studio
Versions:
@cap-js/cds-typer: 0.11.1
@cap-js/db-service: 1.3.2
@cap-js/sqlite: 1.3.1
@sap/cds: 7.3.1
@sap/cds-common-content: 1.2.0
@sap/cds-compiler: 4.3.2
@sap/cds-dk: 7.3.1
@sap/cds-dk (global): 7.3.1
@sap/cds-fiori: 1.1.0
@sap/cds-foss: 4.0.2
@sap/cds-hana: 2.0.0
@sap/cds-mtxs: 1.12.1
@sap/eslint-plugin-cds: 2.6.3
Node.js: v18.14.2
No response
No response
A violation against the OSS Rules of Play has been detected.
Rule ID: rl-assigned_teams-3
Explanation: Does it have enough admins on GitHub? No
Find more information at: https://sap.github.io/fosstars-rating-core/oss_rules_of_play_rating.html
Referenced types can sometimes be empty nowadays. For example, an entity Foo
that has no actions defined will result in a class:
class Foo {
static actions: {}
}
While syntactically correct, some linters will suggest:
Don't use `{}` as a type. `{}` actually means "any non-nullish value".
- If you want a type meaning "any object", you probably want `object` instead.
- If you want a type meaning "any value", you probably want `unknown` instead.
- If you want a type meaning "empty object", you probably want `Record<string, never>` instead.
- If you really want a type meaning "any non-nullish value", you probably want `NonNullable<unknown>`
instead.
While the types should generally be excluded from linting in projects, I believe this is a change we can easily make to relieve users of some error messages.
Note that this also extends to actions that return empty types:
class Bar {
static actions: {
baz: { (): any; __parameters: {}; __returns: any };
};
}
Generating Record<string, never>
where we need a type, or not generating the field when empty (applies to .action
) is probably the best solution.
See the linter suggestions above.
Actions are generated here: https://github.com/cap-js/cds-typer/blob/main/lib/visitor.js#L190
Action parameter lists are generated here: https://github.com/cap-js/cds-typer/blob/main/lib/visitor.js#L307
The latter type is used in handler implementations, like:
myCdsService.on('myAction', (a, b, c) => ...)
// ^ types of a, b, c are derived from the generated types
We should investigate if using Record<string, never>
for actions without parameters still produces the desired code completion when implementing the handler.
TypeScript
When defining an entity within a namespace, such as:
entity Name.Something {
key something: String;
}
entity Name.SomethingElse {
key something: String;
}
entity Name {
key something: String;
somethingElse: Association to Name.SomethingElse
}
The namespace is (atleast in my test) created on the top position of the file. Yet that results in TypeScript errors:
A namespace declaration cannot be located prior to a class or function with which it is merged.
Class 'Something' used before it's declaration.
The generated types shouldn't have TypeScript errors.
No response
- **OS**: MacOs
- **Node**: v20.10.0
- **npm**:
- **cds-typer**: 0.13.0
- **cds**: 7.4.2
No response
No response
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.