Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add static property elements to entity classes #345

Merged
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/).
## Version 0.28.0 - TBD
### Added
- Schema definition for `cds.typer` options in `package.json` and `.cdsrc-*.json` files
- Added a static `elements` property to all entities, which allows access to the `LinkedDefinitions` instance of an entity's elements
- Schema definition for `typescript` cds build task.

### Fixed
Expand Down
4 changes: 4 additions & 0 deletions lib/components/basedefs.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ const timeRegex = '`${number}${number}:${number}${number}:${number}${number}`'
const baseDefinitions = new SourceFile('_')
// FIXME: this should be a library someday
baseDefinitions.addPreamble(`
import { type } from '@sap/cds'
export type ElementsOf<T> = {[name in keyof Required<T>]: type }
export namespace Association {
export type to <T> = T;
export namespace to {
Expand Down
8 changes: 8 additions & 0 deletions lib/components/wrappers.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,13 @@ const createKey = t => `${base}.Key<${t}>`
*/
const createKeysOf = t => `${base}.KeysOf<${t}>`

/**
* Wraps type into ElementsOf type.
* @param {string} t - the type name.
* @returns {string}
*/
const createElementsOf = t => `${base}.ElementsOf<${t}>`

/**
* Wraps type into association to scalar.
* @param {string} t - the singular type name.
Expand Down Expand Up @@ -102,6 +109,7 @@ module.exports = {
createArrayOf,
createKey,
createKeysOf,
createElementsOf,
createObjectOf,
createPromiseOf,
createUnionOf,
Expand Down
11 changes: 10 additions & 1 deletion lib/visitor.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ const { SourceFile, FileRepository, Buffer, Path } = require('./file')
const { FlatInlineDeclarationResolver, StructuredInlineDeclarationResolver } = require('./components/inline')
const { Resolver } = require('./resolution/resolver')
const { LOG } = require('./logging')
const { docify, createPromiseOf, createUnionOf, createKeysOf } = require('./components/wrappers')
const { docify, createPromiseOf, createUnionOf, createKeysOf, createElementsOf } = require('./components/wrappers')
const { csnToEnumPairs, propertyToInlineEnumName, isInlineEnumType, stringifyEnumType } = require('./components/enum')
const { isReferenceType } = require('./components/reference')
const { empty } = require('./components/typescript')
Expand Down Expand Up @@ -167,6 +167,14 @@ class Visitor {
buffer.add(`declare static readonly keys: ${createKeysOf(clean)}`)
}

/**
* @param {Buffer} buffer - the buffer to write the elements into
* @param {string} clean - the clean name of the entity
*/
#printStaticElements(buffer, clean) {
buffer.add(`declare static readonly elements: ${createElementsOf(clean)}`)
}

/**
* Transforms an entity or CDS aspect into a JS aspect (aka mixin).
* That is, for an element A we get:
Expand Down Expand Up @@ -281,6 +289,7 @@ class Visitor {
buffer.add(`static readonly kind: 'entity' | 'type' | 'aspect' = '${entity.kind}';`)
}
this.#printStaticKeys(buffer, clean)
this.#printStaticElements(buffer, clean)
this.#printStaticActions(entity, buffer, ancestorInfos, file)
}, '};') // end of generated class
}, '}') // end of aspect
Expand Down
19 changes: 19 additions & 0 deletions test/unit/files/elements/model.cds
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
namespace elements_test;

aspect A1 {
A_f1 : String;
A_f2 : String;
}

entity E1 {
key ID: Integer;
a : String;
b : Integer;
}

entity E2 : A1 {
key ID: String;
d: Integer;
}

entity P1 as projection on E2;
26 changes: 26 additions & 0 deletions test/unit/files/elements/model.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import cds from '@sap/cds'
import { E1, E2, P1 } from '#cds-models/elements_test'

E1.elements
E1.elements.ID
E1.elements.a
E1.elements.b
// @ts-expect-error
E1.elements.nonExistent

E2.elements
E2.elements.d // from entity E1
E2.elements.A_f1 // from aspect A1

// check projection
P1.elements
P1.elements.ID
P1.elements.d
P1.elements.A_f1
P1.elements.A_f2

// check LinkedDefinitions types
E1.elements.a.type
E1.elements.a.kind
E1.elements.a.items
E1.elements.a instanceof cds.builtin.classes.String
Loading