Giter Club home page Giter Club logo

cds-typer's People

Contributors

alyonavyshnevska avatar chgeo avatar danjoa avatar daogrady avatar dellagustin-sap avatar dependabot[bot] avatar mnkiefer avatar muellinho avatar nils avatar ogrady avatar ospo-bot[bot] avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

cds-typer's Issues

[BUG] String enum in composition of many potentially not supported

Is there an existing issue for this?

  • I have searched the existing issues

Nature of Your Project

TypeScript

Current Behavior

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.

Expected Behavior

I would've expected taggedElements_hierarchyLevel to exist.

Steps To Reproduce

No response

Environment

- **OS**: Mac OS
- **Node**: v20.10.0
- **npm**: 10.2.3
- **cds-typer**: 0.12.0
- **cds**: 7.4.1

Repository Containing a Minimal Reproducible Example

No response

Anything else?

No response

[BUG] Projection on Anonymous Types Broken

Is there an existing issue for this?

  • I have searched the existing issues

Nature of Your Project

JavaScript, TypeScript

Current Behavior

Projecting an entity B on an anonymous type T in another entity A does not generate the projection.

Expected Behavior

B should be generated as projection on A.T.

Steps To Reproduce

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.

Environment

- **OS**:
- **Node**:
- **npm**:
- **cds-typer**: 0.10.0
- **cds**:

Repository Containing a Minimal Reproducible Example

No response

Anything else?

No response

[BUG] Invalid handling of composition of aspects

Is there an existing issue for this?

  • I have searched the existing issues

Nature of Your Project

TypeScript

Current Behavior

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>;

Expected Behavior

No errors in TS definitions.

Steps To Reproduce

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;
}

Environment

- **OS**: Windows 10
- **Node**: 18.17.1
- **yarn**: 4.0.2
- **cds-typer**: 0.15.0
- **cds**: 7.5.1

Repository Containing a Minimal Reproducible Example

No response

Anything else?

No response

[BUG] Action with arrayed input parameter containing string enum yields to failed typer compilation

Is there an existing issue for this?

  • I have searched the existing issues

Nature of Your Project

TypeScript

Current Behavior

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

Expected Behavior

I'd expect the compilation to work.

Steps To Reproduce

No response

Environment

- **OS**: MacOs
- **Node**: v20.10.0.
- **npm**:
- **cds-typer**: 0.13.0
- **cds**:7.4.2

Repository Containing a Minimal Reproducible Example

No response

Anything else?

No response

CDS type "Date" to TypeScript type "Date" conversion is misleading/incorrect

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

[BUG] Imported remote service type generation fails

Is there an existing issue for this?

  • I have searched the existing issues

Nature of Your Project

TypeScript

Current Behavior

Hi,

When importing the SAP Build Process Automation workflow runtime API from the Business Accelerator HUB, the cds-typer crashes with following error log:
image

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

Expected Behavior

cds-typer not to crash and generate the types successfully.

Steps To Reproduce

Described in current behavior

Environment

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

Repository Containing a Minimal Reproducible Example

No response

Anything else?

No response

[QUESTION] Receiving an usual error from TypeScript when I try and reference things with strings

Question

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> {}

[BUG] Allow Readable as a return type for actions LargeBinary

Is there an existing issue for this?

  • I have searched the existing issues

Nature of Your Project

TypeScript

Current Behavior

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

Expected Behavior

Generated Types:
export declare const generateDocument: { (templateId: string, documentContext: string): Buffer | string | Readable, __parameters: {templateId: string, documentContext: string}, __returns: Buffer | string | Readable };

Steps To Reproduce

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.

Environment

- **OS**: Ubuntu 22.04
- **Node**: v18.16.1
- **npm**: 9.5.1
- **cds-typer**: 0.11.1
- **cds**: 7.3.0

Repository Containing a Minimal Reproducible Example

No response

Anything else?

No response

[IMPROVEMENT] Remove `.drafts` Property From Entities That Are Not Actually Draftable

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.

  • check with the compiler team whether there is a surefire way to determine an entity's draftability
  • if possible, get rid of the current voodoo where we propagate annotations through the CSN
  • make sure a static .drafts property is only exposed when the entity can actually be drafted during runtime

[BUG] Type generation fails on functions with an enum return value that is accessed through an entity

Is there an existing issue for this?

  • I have searched the existing issues

Nature of Your Project

TypeScript

Current Behavior

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

Expected Behavior

cds-typer should not fail on the given example.

Steps To Reproduce

# 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.
    }
}

Environment

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

Repository Containing a Minimal Reproducible Example

https://github.com/rgrenz/cds-typer-issue

Anything else?

No response

[QUESTION] Aren't types generated for a view?

Question

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

[BUG] Action with string enum input parameter results in an incorrect type

Is there an existing issue for this?

  • I have searched the existing issues

Nature of Your Project

TypeScript

Current Behavior

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)

Expected Behavior

I'd expect a correct type returned from the creation.

Steps To Reproduce

No response

Environment

- **OS**: MacOs
- **Node**: v20.10.0.
- **npm**:
- **cds-typer**: 0.13.0
- **cds**:7.4.2

Repository Containing a Minimal Reproducible Example

No response

Anything else?

No response

[BUG] Composition of aspects fails in 0.11.1

Is there an existing issue for this?

  • I have searched the existing issues

Nature of Your Project

TypeScript

Current Behavior

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)

Expected Behavior

Types are generated.

Steps To Reproduce

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.

Environment

- **OS**: WIN 11
- **Node**: v18.16.1
- **npm**: 9.5.1
- **cds-typer**: 0.11.1
- **cds**: 7.2.1

Repository Containing a Minimal Reproducible Example

https://github.com/fabiantschirschnitz/issue_cds_typer/tree/aspect_error

Anything else?

No response

[BUG] enum value resolution fails for actions

Is there an existing issue for this?

  • I have searched the existing issues

Nature of Your Project

TypeScript

Current Behavior

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.

Expected Behavior

String values are emitted or just the enum type name as in 0.14.0

Steps To Reproduce

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.

Environment

- **OS**: win11
- @sap/cds: 7.5.1
- Node.js: v18.16.1
- **cds-typer**: 0.15.0

Repository Containing a Minimal Reproducible Example

sorry, not this time. but please let me know, if the error is till unclear :)

Anything else?

fyi @nlaenger

[BUG] `index.js` For Entities with @singular and @plural Broken

Current Behavior

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

Expected Behavior

// index.js
module.exports.Y = csn.Z
module.exports.Z = csn.Z

[BUG] CDS-ts crashes with latest version of [email protected]

Is there an existing issue for this?

  • I have searched the existing issues

Nature of Your Project

TypeScript

Current Behavior

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

Expected Behavior

NodeJS server should start with [email protected]

Steps To Reproduce

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
  1. schema.cds
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()
  }
}

Environment

- **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      |

Repository Containing a Minimal Reproducible Example

No response

Anything else?

No response

[QUESTION] How to access data from request object for Actions

Question

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;
}

Question

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

[BUG] ID properties from associations are not brought through when type CUID

Is there an existing issue for this?

  • I have searched the existing issues

Nature of Your Project

TypeScript

Current Behavior

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?

Expected Behavior

the _ID property from CUID aspect are available on parent entities.

Steps To Reproduce

See description above.

Environment

- **OS**: Mac OS
- **Node**: 18
- **npm**: 10 (also 9)
- **cds-typer**: 0.7.0
- **cds**: 7.1.2

Repository Containing a Minimal Reproducible Example

No response

Anything else?

No response

[BUG] Runtime import issue with String Enums

Is there an existing issue for this?

  • I have searched the existing issues

Nature of Your Project

TypeScript

Current Behavior

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 .

Expected Behavior

You should be able to runtime import without issues even when String Enums are available.

Steps To Reproduce

No response

Environment

- **OS**: MacOs
- **Node**: v20.10.0.
- **npm**:
- **cds-typer**: 0.13.0
- **cds**:7.4.2

Repository Containing a Minimal Reproducible Example

No response

Anything else?

No response

[BUG] Typer crashes on basic cds model

Is there an existing issue for this?

  • I have searched the existing issues

Nature of Your Project

TypeScript

Current Behavior

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)

Expected Behavior

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

Steps To Reproduce

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.

Environment

- **OS**: Windows
- **Node**: v18.16.1
- **npm**: 9.5.1
- **cds-typer**: 0.10.0
- **cds**: 7.2.1

Repository Containing a Minimal Reproducible Example

https://github.com/fabiantschirschnitz/issue_cds_typer

Anything else?

No response

[QUESTION] Properties of response in capital letters?

Description

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?

image
image

Details

Versions of CDS tools:
image
Version of cds-typer: 0.5.0

Sample CDS

image

Generated index.ts

image

[FEATURE] Missing types for text tables/localized properties

Is there an existing issue for this?

  • I have searched the existing issues

Nature of Your Project

TypeScript

Current Behavior

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.

Expected Behavior

A new classes are generated for the text tables.

Steps To Reproduce

No response

Environment

- **OS**:
- **Node**:
- **npm**:
- **cds-typer**: 
- **cds**:

Repository Containing a Minimal Reproducible Example

No response

Anything else?

No response

[FEATURE] Consolidate Consumed CSN Flavours

Description

Two Flavours

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.

Ramifications

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.

Suggested Solution

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.

Alternatives

Wait for universal CSN or modify xtended CSN even more to be closer to inferred CSN.

Additional Context

No response

[BUG] namespace missing in CQL queries

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.

image

Also mentioned in following community question: https://answers.sap.com/questions/13938363/cap-typescript.html

Details

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 Code

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 });

[BUG] Path with spaces crash the type generation process in windows

Is there an existing issue for this?

  • I have searched the existing issues

Nature of Your Project

TypeScript

Current Behavior

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: []
}

Expected Behavior

Type generation should work as expected.

Steps To Reproduce

  1. Create a cap project with typescript.
  2. Add a simple entity
  3. Move your project folder to a path with spaces
  4. Try saving CDS file and check the output logs in CDS channel
  5. Type generation fails

Environment

- **OS**: Windows
- **Node**:
- **npm**:
- **cds-typer**: 0.15.0
- **cds**:

Repository Containing a Minimal Reproducible Example

No response

Anything else?

No response

[BUG] Startup error when using enum constant at runtime

Is there an existing issue for this?

  • I have searched the existing issues

Nature of Your Project

TypeScript

Current Behavior

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]))
                                                                                                       ~~~~

Expected Behavior

I should be able to reference enum values using the const that is generated by cds-typer without any error.

Steps To Reproduce

  1. Define the enum in a .cds file:
namespace db;

type SampleEnum : String(3) enum {
    a = 'AAA';
    b = 'BBB';
}
  1. Import and reference the enum in a .ts file (there is no compiler error at this step):
import { SampleEnum } from "#cds-models/db";
...
someVariable === SampleEnum.a;
  1. Launch the application using:
cds-ts watch
  1. The error appears

Environment

- **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

Repository Containing a Minimal Reproducible Example

https://github.com/lorenzofratus/cds-typer-enum-bug

Anything else?

Please let me know if I'm missing some configuration or if I can provide more information.

[BUG] Augmented projection does not supply types

Is there an existing issue for this?

  • I have searched the existing issues

Nature of Your Project

JavaScript, TypeScript

Current Behavior

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.

Expected Behavior

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.

Steps To Reproduce

One can reproduce the behaviour with the ext-service-consume-ui branch in the Risk Management Sample:

  1. Clone the sample branch and add cds-typer:
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
  1. add an association to the Suppliers entity (it is not necessary, because the select will also not be generated):
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
}
  1. generate types
npx @cap-js/cds-typer '*' --outputDirectory @cds-models
  1. Check the generated Types
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 &quot;Authorization group&quot; 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 &quot;Group&quot; 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 &quot;Zentrale fรผr Coorganisation GmbH&quot; 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 &quot;Organization&quot;, 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) {}

Environment

- **OS**:
- **Node**: v18.18.0
- **npm**: 9.8.1
- **cds-typer**: 0.11.1
- **cds**: 6.8.4

Repository Containing a Minimal Reproducible Example

No response

Anything else?

No response

[BUG] App crashes with unused enum types

Is there an existing issue for this?

  • I have searched the existing issues

Nature of Your Project

TypeScript

Current Behavior

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')

Expected Behavior

The app should not crash on startup.

Steps To Reproduce

// 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);

Environment

@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      |

Repository Containing a Minimal Reproducible Example

https://github.com/rgrenz/cds-typer-issue/tree/unused-enum-generation

Anything else?

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).

Add Tests for Generated `index.js` Files

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.

[QUESTION] How to integrate cds-typer into the CI

Question

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

[BUG] "excluding" clause in CDS projections not applied for compiled TS models

Is there an existing issue for this?

  • I have searched the existing issues

Nature of Your Project

TypeScript

Current Behavior

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<...>;
}

Expected Behavior

Compiled TypeScript models should leave out properties which are marked as excluded on CDS layer.

class TestObjects {
    ID: string;
    name: string;
    description: string | null;
}

Steps To Reproduce

No response

Environment

- **OS**: MacOS 14.1.1
- **Node**: 18.18.2
- **npm**: 9.8.1
- **cds-typer**: 0.12.0
- **cds**: 7.3.1

Repository Containing a Minimal Reproducible Example

No response

Anything else?

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 };
}

cds.test + cds-typer + ts

Question

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

[BUG] Types for CDS models with namespace from separate node module get wrongly generated

Is there an existing issue for this?

  • I have searched the existing issues

Nature of Your Project

TypeScript

Current Behavior

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:
image

Fixing this manually as below, solves the issue:
image

Expected Behavior

Generated types should include the prefix as generated in the import

Steps To Reproduce

No response

Environment

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

Repository Containing a Minimal Reproducible Example

No response

Anything else?

No response

[BUG] CDS type aliasing causes duplicate TS type definitions

Is there an existing issue for this?

  • I have searched the existing issues

Nature of Your Project

TypeScript

Current Behavior

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>;

Expected Behavior

No response

Steps To Reproduce

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;

Environment

- **OS**: Windows 10
- **Node**: 18.17.1
- **yarn**: 4.0.2
- **cds-typer**: 0.15.0
- **cds**: 7.5.1

Repository Containing a Minimal Reproducible Example

No response

Anything else?

No response

Bug : index.ts file contains error when the aspect elements are used in event parameters.

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

Missing type checking for non existing properties of generated types

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):
image

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:
image

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;
  };
}
...

image

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

[BUG] Enum values all undefined

Is there an existing issue for this?

  • I have searched the existing issues

Nature of Your Project

TypeScript

Current Behavior

When the projects get build and run in production, the ENUM values are all undefined.
image

this seems to be an issue with the generation of the enum in the index.js of the by cds-typer generated code

image

Expected Behavior

The ENUM should be populated

Steps To Reproduce

  1. clone the project : https://github.com/sebbi08/cds-typer-issue/tree/bug-enum
  2. debug npm run start and inspect the value if a in the test-service.ts

Environment

- **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      |

Repository Containing a Minimal Reproducible Example

https://github.com/sebbi08/cds-typer-issue/tree/bug-enum

Anything else?

No response

CDS Types containing another type, using a one to many relation, results into an incomplete type definition

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

[FEATURE] Refinement of Type Generation in CDS-Typer for Optional / Nullable Fields

Question

Background

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.

Current Behavior

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;
    [...]
};

Expected Behavior

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.

[BUG] Delimited identifier syntax potentially not supported

Is there an existing issue for this?

  • I have searched the existing issues

Nature of Your Project

TypeScript

Current Behavior

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.

Expected Behavior

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

Steps To Reproduce

See data above.

Environment

- **OS**: Mac OS
- **Node**: v20.10.0
- **npm**: 10.2.3
- **cds-typer**: 0.12.0
- **cds**: 7.4.1

Repository Containing a Minimal Reproducible Example

No response

Anything else?

No response

[BUG] Missing "drafts" property to register handlers for draft enabled service

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();
  }
}

Possible solution

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

Details

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

[QUESTION] Deconstructed variables have type any

Question

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:

  1. Saving a .cds file doesn't autogenerate the types for me.
    Using the CLI with npx however works and generates the @cds-models directory.
  2. When I require and deconstruct my service definition (either via subpath or regular path) in my services init function, the variables are typed any.
    If however I switch to an 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

[BUG] Drafts - types are missing draft-management fields

Is there an existing issue for this?

  • I have searched the existing issues

Nature of Your Project

TypeScript

Current Behavior

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:

  • DraftAdministrativeData_DraftUUID
  • HasDraftEntity
  • HasActiveEntity
  • IsActiveEntity

Currently it seems like these fields are not covered by the typer functionality.

Expected Behavior

Having these administrative fields available, so we can access the draft_uuid to e.g. add additional entities to a composition through code.

Steps To Reproduce

No response

Environment

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

Repository Containing a Minimal Reproducible Example

No response

Anything else?

No response

[FEATURE] Friendly Empty Types

Description

Referenced types can sometimes be empty nowadays. For example, an entity Foothat 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 };
  };
}

Suggested Solution

Generating Record<string, never> where we need a type, or not generating the field when empty (applies to .action) is probably the best solution.

Alternatives

See the linter suggestions above.

Additional Context

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.

[BUG] Scoped Definitions translated into Typescript Namespaces are generated at the wrong position

Is there an existing issue for this?

  • I have searched the existing issues

Nature of Your Project

TypeScript

Current Behavior

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.

Expected Behavior

The generated types shouldn't have TypeScript errors.

Steps To Reproduce

No response

Environment

- **OS**: MacOs
- **Node**: v20.10.0
- **npm**:
- **cds-typer**: 0.13.0
- **cds**: 7.4.2

Repository Containing a Minimal Reproducible Example

No response

Anything else?

No response

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.