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

Retrieve keys from both flavours of CSN #126

Merged
merged 3 commits into from
Dec 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,14 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/).
### Fixed
- Inline enums are now available during runtime as well
- Inline enums can now be used as action parameter types as well. These enums will not have a runtime representation, but will only assert type safety!
- Foreign keys of projection entities are now propagated as well

## Version 0.14.0 - 2023-12-13
### Added
- Entities that are database views now also receive typings

## Version 0.13.0 - 2023-12-06
### Changes
### Changed
- Enums are now generated ecplicitly in the respective _index.js_ files and don't have to extract their values from the model at runtime anymore

### Added
Expand Down
2 changes: 1 addition & 1 deletion lib/csn.js
Original file line number Diff line number Diff line change
Expand Up @@ -240,4 +240,4 @@ const isView = entity => entity.query && !entity.projection
*/
const isUnresolved = entity => entity._unresolved === true

module.exports = { amendCSN, isView, isUnresolved }
module.exports = { amendCSN, isView, isUnresolved, propagateForeignKeys }
23 changes: 21 additions & 2 deletions lib/visitor.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

const util = require('./util')

const { amendCSN, isView, isUnresolved } = require('./csn')
const { amendCSN, isView, isUnresolved, propagateForeignKeys } = require('./csn')
// eslint-disable-next-line no-unused-vars
const { SourceFile, baseDefinitions, Buffer } = require('./file')
const { FlatInlineDeclarationResolver, StructuredInlineDeclarationResolver } = require('./components/inline')
Expand Down Expand Up @@ -63,6 +63,7 @@ class Visitor {
*/
constructor(csn, options = {}, logger = new Logger()) {
amendCSN(csn.xtended)
propagateForeignKeys(csn.inferred)
this.options = { ...defaults, ...options }
this.logger = logger
this.csn = csn
Expand Down Expand Up @@ -130,6 +131,24 @@ class Visitor {
}
}

/**
* Retrieves all the keys from an entity.
* That is: all keys that are present in both inferred, as well as xtended flavour.
* @returns {[string, object][]} array of key name and key element pairs
*/
#keys(name) {
// FIXME: this is actually pretty bad, as not only have to propagate keys through
// both flavours of CSN (see constructor), but we are now also collecting them from
// both flavours and deduplicating them.
// xtended contains keys that have been inherited from parents
// inferred contains keys from queried entities (thing `entity Foo as select from Bar`, where Bar has keys)
// So we currently need them both.
return Object.entries({
...this.csn.inferred.definitions[name]?.keys ?? {},
...this.csn.xtended.definitions[name]?.keys ?? {}
})
}

/**
* Transforms an entity or CDS aspect into a JS aspect (aka mixin).
* That is, for an element A we get:
Expand Down Expand Up @@ -168,7 +187,7 @@ class Visitor {
// lookup in cds.definitions can fail for inline structs.
// We don't really have to care for this case, as keys from such structs are _not_ propagated to
// the containing entity.
for (const [kname, kelement] of Object.entries(this.csn.xtended.definitions[element.target]?.keys ?? {})) {
for (const [kname, kelement] of this.#keys(element.target)) {
if (this.resolver.getMaxCardinality(element) === 1) {
kelement.isRefNotNull = !!element.notNull || !!element.key
this.visitElement(`${ename}_${kname}`, kelement, file, buffer)
Expand Down