Socket
Socket
Sign inDemoInstall

@sap/cds-compiler

Package Overview
Dependencies
Maintainers
1
Versions
106
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@sap/cds-compiler - npm Package Compare versions

Comparing version 2.1.4 to 2.1.6

doc/DeprecatedOptions.md

11

bin/cdsc.js

@@ -33,2 +33,3 @@ #!/usr/bin/env node

const { addLocalizationViews } = require('../lib/transform/localized');
const { availableBetaFlags } = require('../lib/base/model');

@@ -119,11 +120,3 @@ // Note: Instead of throwing ProcessExitError, we would rather just call process.exit(exitCode),

if(cmdLine.options.betaMode) {
cmdLine.options.beta = {
'foreignKeyConstraints': true,
'toRename': true,
'addTextsLanguageAssoc': true,
'assocsWithParams': true,
'hanaAssocRealCardinality': true,
'mapAssocToJoinCardinality': true,
'ignoreAssocPublishingInUnion': true,
}
cmdLine.options.beta = availableBetaFlags;
}

@@ -130,0 +123,0 @@ if (cmdLine.options.deprecated) {

# ChangeLog for cds compiler and backends
<!-- markdownlint-disable MD024 -->
<!-- markdownlint-disable MD004 -->
<!-- (no-duplicate-heading)-->

@@ -9,2 +10,21 @@

## Version 2.1.6 - 2021-04-14
### Fixed
- Do not unjustified complain about `$self` comparisons.
- Auto-exposed entities are represented as projections in the CSN.
- to.sql/to.hdi:
+ Revert change "Default values are no longer propagated from the principal to the generated foreign key element." from version 2.1.0
+ Fix regression where localized convenience views for temporal entities used keys in the from clause that did not exist on the texts-entity
+ Mixin associations are properly removed and are not rendered into views anymore
- to.hdi(.migration): Ensure filenames for `.hdbindex` files stay compatible to V1
- for.odata: An association as a type of action's parameter or return type now signals an error
- to.edm(x):
+ `@Capabilities` annotations remain on the containees entity type
+ In containment mode don't render foreign keys of the containment constituting 'up' association in the containee
as primary key refs.
+ Revert change "Default values are no longer propagated from the principal to the generated foreign key element." from version 2.1.0
+ Allow `--odata-proxies` and/or `--odata-x-service-refs` in combination with `--odata-format=flat` and `--version=v4`
## Version 2.1.4 - 2021-03-31

@@ -35,5 +55,5 @@

+ Allow the user to define draft actions for annotation purposes
* `draftPrepare(SideEffectsQualifier: String) returns <ET>`,
* `draftActivate() returns <ET>`,
* `draftEdit(PreserveChanges: Boolean) returns <ET>`
+ `draftPrepare(SideEffectsQualifier: String) returns <ET>`,
+ `draftActivate() returns <ET>`,
+ `draftEdit(PreserveChanges: Boolean) returns <ET>`
- to.edm(x):

@@ -115,4 +135,4 @@ + Warn about non-applicable annotations.

+ Temporal rendering:
* `@cds.valid.from` is not `Edm.KeyRef` anymore.
* `@cds.valid.key` is rendered as `@Core.AlternateKeys`.
+ `@cds.valid.from` is not `Edm.KeyRef` anymore.
+ `@cds.valid.key` is rendered as `@Core.AlternateKeys`.
+ Downgrade message "`<Term>` is not applied" from warning to info.

@@ -133,8 +153,8 @@ + Update Vocabularies 'Aggregation', 'Capabilities', 'Core', 'Validation'.

+ Changed type mappings for `--dialect=sqlite`:
* `cds.Date` -> `DATE_TEXT`
* `cds.Time` -> `TIME_TEXT`
* `cds.Timestamp` -> `TIMESTAMP_TEXT`
* `cds.DateTime` -> `TIMESTAMP_TEXT`
* `cds.Binary` -> `BINARY_BLOB`
* `cds.hana.Binary` -> `BINARY_BLOB`
+ `cds.Date` -> `DATE_TEXT`
+ `cds.Time` -> `TIME_TEXT`
+ `cds.Timestamp` -> `TIMESTAMP_TEXT`
+ `cds.DateTime` -> `TIMESTAMP_TEXT`
+ `cds.Binary` -> `BINARY_BLOB`
+ `cds.hana.Binary` -> `BINARY_BLOB`
+ Don't check missing type facets.

@@ -205,3 +225,3 @@ - to.hdbcds:

+ Rendering of `@Validation.AllowedValue` for elements of type enum annotated with `@assert.range`:
* Add `@Core.Description`, if the enum symbol has a `@Core.Description`, `@description` or document comments.
+ Add `@Core.Description`, if the enum symbol has a `@Core.Description`, `@description` or document comments.
+ Primary key aliases are now the path basenames, colliding aliases are numbered.

@@ -238,2 +258,8 @@ + Fix a bug in constraint calculation if principal has no primary keys.

## Version 1.50.4 - 2021-04-06
### Fixed
- to.hdbcds: CDS and HANA CDS types inside cast expressions are mapped to their SQL-counterparts, as the CDS types can't be used in a cast.
## Version 1.50.2 - 2021-03-19

@@ -240,0 +266,0 @@

@@ -228,3 +228,3 @@ /** @module API */

.reduce((previous, current) => {
const hdiArtifactName = remapName(nameMapping[current.name], sqlCSN);
const hdiArtifactName = remapName(nameMapping[current.name], sqlCSN, k => !k.endsWith('.hdbindex'));
previous[hdiArtifactName] = current.sql;

@@ -236,3 +236,3 @@ return previous;

Object.keys(sqlsNotToSort).forEach((key) => {
sorted[remapName(key, sqlCSN)] = sqlsNotToSort[key];
sorted[remapName(key, sqlCSN, k => !k.endsWith('.hdbindex'))] = sqlsNotToSort[key];
});

@@ -243,3 +243,3 @@

return remapNames(flattenResultStructure(intermediateResult), sqlCSN);
return remapNames(flattenResultStructure(intermediateResult), sqlCSN, k => !k.endsWith('.hdbindex'));
}

@@ -253,9 +253,10 @@ /**

* @param {CSN.Model} csn SQL transformed CSN
* @param {Function} filter
* @returns {object} New result structure
*/
function remapNames(dict, csn) {
function remapNames(dict, csn, filter) {
const result = Object.create(null);
for (const [ key, value ] of Object.entries(dict)) {
const name = remapName(key, csn);
const name = remapName(key, csn, filter);
result[name] = value;

@@ -273,11 +274,16 @@ }

* @param {CSN.Model} csn SQL transformed CSN
* @param {Function} filter Filter for keys not to remap
* @returns {string} Remapped filename
*/
function remapName(key, csn) {
const lastDot = key.lastIndexOf('.');
const prefix = key.slice(0, lastDot);
const suffix = key.slice(lastDot);
function remapName(key, csn, filter = () => true) {
if (filter(key)) {
const lastDot = key.lastIndexOf('.');
const prefix = key.slice(0, lastDot);
const suffix = key.slice(lastDot);
const remappedName = getFileName(prefix, csn);
return remappedName + suffix;
const remappedName = getFileName(prefix, csn);
return remappedName + suffix;
}
return key;
}

@@ -362,4 +368,8 @@

const suffix = `.${ kind }`;
for (const [ name, sqlStatement ] of Object.entries(artifacts))
result.push({ name: getFileName(name, afterImage), suffix, sql: sqlStatement });
for (const [ name, sqlStatement ] of Object.entries(artifacts)) {
if ( kind !== 'hdbindex' )
result.push({ name: getFileName(name, afterImage), suffix, sql: sqlStatement });
else
result.push({ name, suffix, sql: sqlStatement });
}
}

@@ -366,0 +376,0 @@ return result;

@@ -86,3 +86,3 @@ 'use strict';

if(options.testMode){
const sorted = sortCsn(forHanaCsn, true);
const sorted = sortCsn(forHanaCsn, options);
result.hdbcds = toHdbcdsSource(sorted, options);

@@ -95,3 +95,3 @@ } else {

if (options.toHana.csn) {
result.csn = options.testMode ? sortCsn(forHanaCsn) : forHanaCsn;
result.csn = options.testMode ? sortCsn(forHanaCsn, options) : forHanaCsn;
}

@@ -313,3 +313,3 @@

if (transformedOptions.options.toSql.csn) {
result.csn = options.testMode ? sortCsn(forSqlCsn, true) : forSqlCsn;
result.csn = options.testMode ? sortCsn(forSqlCsn, options) : forSqlCsn;
}

@@ -316,0 +316,0 @@

@@ -13,2 +13,25 @@ 'use strict';

/**
* Object of all available beta flags that will be enabled/disabled by `--beta-mode`
* through cdsc. Only intended for INTERNAL USE.
* NOT to be used by umbrella, etc.
*
* @type {{[flag: string]: boolean}} Indicates whether it is enabled by --beta-mode or not.
* @private
*/
const availableBetaFlags = {
// enabled by --beta-mode
foreignKeyConstraints: true,
toRename: true,
addTextsLanguageAssoc: true,
assocsWithParams: true,
hanaAssocRealCardinality: true,
mapAssocToJoinCardinality: true,
ignoreAssocPublishingInUnion: true,
// disabled by --beta-mode
pretransformedCSN: false,
renderSQL: false,
nestedServices: false,
};
/**
* Test for early-adaptor feature, stored in option `beta`(new-style) / `betaMode`(old-style)

@@ -220,2 +243,3 @@ * With that, the value of `beta` is a dictionary of feature=>Boolean.

isBetaEnabled,
availableBetaFlags,
isDeprecatedEnabled,

@@ -222,0 +246,0 @@ queryOps,

@@ -33,3 +33,3 @@ 'use strict';

if (act.returns)
checkReturns.bind(this)(act.returns, path.concat([ 'actions', actName, 'returns' ]));
checkReturns.bind(this)(act.returns, path.concat([ 'actions', actName, 'returns' ]), act.kind);
}

@@ -43,3 +43,3 @@ }

if (art.returns)
checkReturns.bind(this)(art.returns, path.concat('returns'));
checkReturns.bind(this)(art.returns, path.concat('returns'), art.kind);
}

@@ -65,2 +65,10 @@

if (paramType.type && this.csnUtils.isAssocOrComposition(param.type)) {
this.error(null, currPath, { '#': actKind },
{
action: 'An association is not allowed as action\'s parameter type',
function: 'An association is not allowed as function\'s parameter type',
});
}
if (paramType.items && paramType.items.type)

@@ -78,6 +86,15 @@ checkActionOrFunctionParameter.bind(this)(paramType.items, currPath.concat('items'), actKind);

* @param {CSN.Path} currPath path to the returns object
* @param {string} actKind 'action' or 'function'
*/
function checkReturns(returns, currPath) {
function checkReturns(returns, currPath, actKind) {
const finalReturnType = returns.type ? this.csnUtils.getFinalBaseType(returns.type) : returns;
if (this.csnUtils.isAssocOrComposition(finalReturnType)) {
this.error(null, currPath, { '#': actKind },
{
action: 'An association is not allowed as action\'s return type',
function: 'An association is not allowed as function\'s return type',
});
}
if (isBuiltinType(finalReturnType) && this.options.toOdata && this.options.toOdata.version === 'v2') {

@@ -90,3 +107,3 @@ // in ODATA v2 scalar types cannot be returned

if (finalReturnType.items) // check array return type
checkReturns.bind(this)(finalReturnType.items, currPath.concat('items'));
checkReturns.bind(this)(finalReturnType.items, currPath.concat('items'), actKind);
else // check if return type is user definited from the current service

@@ -93,0 +110,0 @@ checkUserDefinedType.bind(this)(finalReturnType, returns.type, currPath);

@@ -8,2 +8,15 @@ 'use strict';

/**
* View parameter for hana must be of scalar type
*
* @param {CSN.Element} member the element to be checked
* @param {string} memberName the elements name
* @param {string} prop which kind of member are we looking at -> only prop "elements"
* @param {CSN.Path} path the path to the member
*/
function checkTypeIsScalar(member, memberName, prop, path) {
if ( prop === 'params' && this.csnUtils.isStructured(member))
this.error(null, path, 'View parameter type must be scalar');
}
/**
* Check that the `type of` information in the given element

@@ -39,2 +52,6 @@ * has proper type information or issue an error otherwise. The element's final type is checked.

}
else if (member._type) {
if ( this.isAspect(member._type) || member._type.kind === 'type' && member._type.$syntax === 'aspect')
this.error('ref-sloppy-type', path, 'A type or an element is expected here');
}
return;

@@ -153,2 +170,2 @@ }

module.exports = { checkTypeDefinitionHasType, checkElementTypeDefinitionHasType };
module.exports = { checkTypeDefinitionHasType, checkElementTypeDefinitionHasType, checkTypeIsScalar };

@@ -25,3 +25,3 @@ 'use strict';

const validateForeignKeys = require('./foreignKeys');
const { checkTypeDefinitionHasType, checkElementTypeDefinitionHasType } = require('./types');
const { checkTypeDefinitionHasType, checkElementTypeDefinitionHasType, checkTypeIsScalar } = require('./types');
const { checkPrimaryKey, checkVirtualElement, checkManagedAssoc } = require('./elements');

@@ -35,2 +35,3 @@ const checkForInvalidTarget = require('./invalidTarget');

rejectParamDefaultsInHanaCds,
checkTypeIsScalar,
];

@@ -89,5 +90,10 @@

* @param {Function[]} [queryValidators=[]] Validations on query-level
* @param {object} iterateOptions can be used to skip certain kinds from being iterated e.g. 'action' and 'function' for hana
* @returns {Function} Function taking no parameters, that cleans up the attached helpers
*/
function _validate(csn, that, memberValidators = [], artifactValidators = [], queryValidators = []) {
function _validate(csn, that,
memberValidators = [],
artifactValidators = [],
queryValidators = [],
iterateOptions = {}) {
const { cleanup } = enrich(csn);

@@ -100,8 +106,13 @@

that.artifact = artifact;
if (memberValidators.length)
forEachMemberRecursively( artifact, memberValidators.map(v => v.bind(that)), path );
if (memberValidators.length) {
forEachMemberRecursively( artifact,
memberValidators.map(v => v.bind(that)),
path,
true,
iterateOptions );
}
if (queryValidators.length && artifact.query)
forAllQueries(artifact.query, queryValidators.map(v => v.bind(that)), path.concat([ 'query' ]));
});
}, iterateOptions);

@@ -130,3 +141,10 @@ return cleanup;

),
forHanaQueryValidators.concat(commonQueryValidators));
forHanaQueryValidators.concat(commonQueryValidators),
{
skip: [
'action',
'function',
'event',
],
});
}

@@ -133,0 +151,0 @@

@@ -556,3 +556,3 @@ // Checks on XSN performed during compile()

return;
if (path0.id === '$self') { // $self (backlink) checks
if (path0.id === '$self' && arg.path.length === 1) { // $self (backlink) checks
checkAssociationArgumentStartingWithSelf( op, elem );

@@ -559,0 +559,0 @@ return;

@@ -87,2 +87,8 @@ // Compiler functions and utilities shared across all phases

const specExpected = {
global: { // for using declaration
envFn: artifactsEnv,
artItemsCount: Number.MAX_SAFE_INTEGER,
useDefinitions: true,
global: 'definitions',
},
// TODO: re-check --------------------------------------------------------

@@ -164,3 +170,3 @@ annotation: { useDefinitions: true, noMessage: true, global: 'vocabularies' },

expr: { // in: from-on,
next: '_$next', escape: 'param', assoc: 'nav',
next: '_$next', dollar: true, escape: 'param', assoc: 'nav',
},

@@ -170,2 +176,3 @@ on: { // TODO: there will also be a 'from-on' (see 'expr')

next: '_$next', // TODO: lexical: ... how to find the (next) lexical environment
dollar: true,
rootEnv: 'elements', // the final environment for the path root

@@ -177,9 +184,10 @@ noDep: true, // do not set dependency for circular-check

next: '_$next', // TODO: lexical: ... how to find the (next) lexical environment
dollar: true,
noDep: true, // do not set dependency for circular-check
}, // TODO: special assoc for only on user
rewrite: {
next: '_$next', escape: 'param', noDep: true, rewrite: true,
next: '_$next', dollar: true, escape: 'param', noDep: true, rewrite: true,
}, // TODO: assertion that there is no next/escape used
'order-by-union': {
next: '_$next', escape: 'param', noDep: true, noExt: true,
next: '_$next', dollar: true, escape: 'param', noDep: true, noExt: true,
},

@@ -192,8 +200,2 @@ // expr TODO: better - on condition for assoc, other on

},
global: { // for using declaration
envFn: artifactsEnv,
artItemsCount: Number.MAX_SAFE_INTEGER,
useDefinitions: true,
global: 'definitions',
},
};

@@ -514,4 +516,7 @@

}
const nodollar = !spec.dollar && spec.next;
const nextProp = spec.next || '_block';
for (let art = env; art; art = art[nextProp]) {
if (nodollar && !art._main) // $self stored in main.$tableAliases
break; // TODO: probably remove _$next link
const e = art.artifacts || art.$tableAliases || Object.create(null);

@@ -586,3 +591,3 @@ const r = e[head.id];

for (const name in extDict) {
if (!name.includes('.') && (!spec.dollar || name[0] !== '$'))
if (!name.includes('.') && (spec.nodollar || name[0] !== '$'))
e[name] = extDict[name];

@@ -589,0 +594,0 @@ }

@@ -249,3 +249,3 @@ // CSN frontend - transform CSN into XSN

onlyWith: 'target',
inKind: [ 'element', 'type' ],
inKind: [ 'element', 'type', 'param' ],
},

@@ -293,3 +293,3 @@ foreignKeys: { // CSN v0.1.0 property -> use 'keys'

optional: [ 'elements' ], // 'elements' for ad-hoc COMPOSITION OF (gensrc style CSN)
inKind: [ 'element', 'type', 'mixin' ],
inKind: [ 'element', 'type', 'mixin', 'param' ],
},

@@ -296,0 +296,0 @@ cardinality: { // there is an extra def for 'from'

@@ -445,5 +445,6 @@ 'use strict';

* @param {(genericCallback|genericCallback[])} callback
* @param {object} iterateOptions can be used to skip certain kinds from being iterated
*/
function forEachDefinition( csn, callback ) {
forEachGeneric( csn, 'definitions', callback );
function forEachDefinition( csn, callback, iterateOptions = {} ) {
forEachGeneric( csn, 'definitions', callback, [], iterateOptions );
}

@@ -462,4 +463,5 @@

* @param {boolean} [ignoreIgnore]
* @param {object} iterateOptions can be used to skip certain kinds from being iterated
*/
function forEachMember( construct, callback, path=[], ignoreIgnore=true) {
function forEachMember( construct, callback, path=[], ignoreIgnore=true, iterateOptions = {}) {
let obj = construct.returns || construct; // why the extra `returns` for actions?

@@ -482,7 +484,9 @@ const obj_path = Array.from(path); // Clone the path

obj = obj.items || obj;
forEachGeneric( obj, 'elements', callback, obj_path );
forEachGeneric( obj, 'enum', callback, obj_path );
forEachGeneric( obj, 'foreignKeys', callback, obj_path );
forEachGeneric( construct, 'actions', callback, path );
forEachGeneric( construct, 'params', callback, path );
const props = ['elements', 'enum', 'foreignKeys', 'actions', 'params'];
props.forEach((prop) => {
if(prop === 'actions' || prop === 'params')
forEachGeneric( construct, prop, callback, path, iterateOptions );
else
forEachGeneric( obj, prop, callback, obj_path, iterateOptions );
});
}

@@ -498,4 +502,5 @@

* @param {boolean} [ignoreIgnore]
* @param {object} iterateOptions can be used to skip certain kinds from being iterated
*/
function forEachMemberRecursively( construct, callback, path=[], ignoreIgnore=true) {
function forEachMemberRecursively( construct, callback, path=[], ignoreIgnore=true, iterateOptions = {}) {
forEachMember( construct, ( member, memberName, prop, subpath ) => {

@@ -507,4 +512,4 @@ if(Array.isArray(callback))

// Descend into nested members, too
forEachMemberRecursively( member, callback, subpath, ignoreIgnore);
}, path, ignoreIgnore);
forEachMemberRecursively( member, callback, subpath, ignoreIgnore, iterateOptions);
}, path, ignoreIgnore, iterateOptions);
}

@@ -522,4 +527,5 @@

* @param {CSN.Path} path
* @param {object} iterateOptions can be used to skip certain kinds from being iterated
*/
function forEachGeneric( obj, prop, callback, path = []) {
function forEachGeneric( obj, prop, callback, path = [], iterateOptions = {}) {
const dict = obj[prop];

@@ -530,2 +536,4 @@ for (const name in dict) {

const dictObj = dict[name];
if(iterateOptions.skip && iterateOptions.skip.includes(dictObj.kind))
continue;
cb( dictObj, name );

@@ -532,0 +540,0 @@ }

@@ -163,3 +163,3 @@

// Render each artifact on its own
forEachDefinition((options && options.testMode) ? sortCsn(csn, true) : csn, (artifact, artifactName) => {
forEachDefinition((options && options.testMode) ? sortCsn(csn, options) : csn, (artifact, artifactName) => {
// This environment is passed down the call hierarchy, for dealing with

@@ -166,0 +166,0 @@ // indentation issues

@@ -43,3 +43,3 @@ // API functions returning the SQL identifier token text for a name

sqlite: {
regularRegex: /^[A-Za-z_$][A-Za-z_$0-9]*$/,
regularRegex: /^[A-Za-z_][A-Za-z_$0-9]*$/,
reservedWords: keywords.sqlite,

@@ -46,0 +46,0 @@ effectiveName: name => name,

@@ -20,4 +20,8 @@ 'use strict';

const { inspectRef } = csnRefs(csn);
// prepare the functions with the compositions and associations across all entities first
// and execute it afterwards because compositions must be processed first
const compositions = [];
const associations = [];
forEachDefinition(csn, (artifact, artifactName) => {
if(!artifact.query){
if(!artifact.query && artifact.kind === 'entity' ){
forAllElements(artifact, artifactName, (parent, elements, path) => {

@@ -28,3 +32,5 @@ // Step I: iterate compositions, enrich dependent keys (in target entity)

if(element.type === 'cds.Composition' && !treatCompositionLikeAssociation(element)) {
foreignKeyConstraintForComposition(element, parent, path.concat([elementName]));
compositions.push(() => {
foreignKeyConstraintForComposition(element, parent, path.concat([elementName]));
});
}

@@ -37,3 +43,5 @@ }

element.type == 'cds.Composition' && treatCompositionLikeAssociation(element)) {
foreignKeyConstraintForAssociation(element, elements, path.concat([elementName]));
associations.push(() => {
foreignKeyConstraintForAssociation(element, elements, path.concat([elementName]));
});
}

@@ -44,2 +52,5 @@ }

});
// create constraints on foreign keys
compositions.forEach(fn => fn());
associations.forEach(fn => fn());
// Step III: Create the final referential constraints from all dependent key <-> parent key pairs stemming from the same $sourceAssociation

@@ -46,0 +57,0 @@ forEachDefinition(csn, collectAndAttachReferentialConstraints);

@@ -12,3 +12,5 @@ 'use strict';

getArtifactDatabaseNameOf,
getElementDatabaseNameOf } = require('../model/csnUtils');
getElementDatabaseNameOf,
isAspect,
} = require('../model/csnUtils');
const { checkCSNVersion } = require('../json/csnVersion');

@@ -123,3 +125,3 @@ const validate = require('../checks/validator');

validate.forOdata(csn, {
error, warning, info, inspectRef, effectiveType, artifactRef, csn, options, csnUtils, services, getFinalBaseType
error, warning, info, inspectRef, effectiveType, artifactRef, csn, options, csnUtils, services, getFinalBaseType, isAspect
});

@@ -126,0 +128,0 @@

@@ -173,3 +173,5 @@ 'use strict';

const elem = entity.elements[originalElement];
if (!elem.key)
// Note: $key is used by forHanaNew.js to indicate that this element was a key in the original,
// user's entity. Keys may have been changed by the backends (e.g. by `@cds.valid.key`)
if (!elem.key && !elem.$key)
columns.push( createColumnLocalizedElement( originalElement, shouldUseJoin ) );

@@ -202,3 +204,3 @@ else if (shouldUseJoin)

const elem = entity.elements[originalElement];
if (elem.key) {
if (elem.key || elem.$key) {
from.on.push( createColumnRef( [ 'localized_1', originalElement ] ));

@@ -295,3 +297,3 @@ from.on.push( '=' );

}
else if (!element.key) {
else if (!element.key && !element.$key) {
// Because in coalesce mode a function is used, localized non-key elements

@@ -316,3 +318,3 @@ // are not directly referenced which results in a `@Core.Computed` annotation.

let keyCount = 0;
const textElements = [];
let textElements = [];

@@ -323,6 +325,6 @@ forEachGeneric(art, 'elements', (elem, elemName /*, prop, path*/) => {

if (elem.key)
if (elem.key || elem.$key)
keyCount += 1;
if (elem.key || elem.localized)
if (elem.key || elem.$key || elem.localized)
textElements.push( elemName );

@@ -335,3 +337,3 @@

if (textElements.length <= keyCount || !keyCount)
if (textElements.length <= keyCount || keyCount <= 0)
// Nothing to do: no localized fields or all localized fields are keys

@@ -361,2 +363,17 @@ return null;

// There may be keys in the original artifact that were added by the core compiler,
// for example elements that are marked @cds.valid.from.
// These keys are not present in the texts entity generated by the compiler.
// So if we don't filter them out, we may generate invalid SQL.
textElements = textElements.filter((elemName) => {
const hasElement = !!textsEntity.elements[elemName];
if (!hasElement && (art.elements[elemName].key || art.elements[elemName].$key))
keyCount--;
return hasElement;
});
if (textElements.length <= keyCount || keyCount <= 0)
// Repeat the check already used above as the number of keys may have changed.
return null;
return textElements;

@@ -419,3 +436,3 @@ }

if ((art.query || art.projection) && elem.localized && !elem.key) {
if ((art.query || art.projection) && elem.localized && !elem.key && !elem.$key) {
// e.g. projections ; ignore if key is present (warning already issued) or

@@ -422,0 +439,0 @@ // if the artifact is an entity (already processed in (1))

@@ -134,2 +134,4 @@ 'use strict';

parent = parent.items;
if (parent.returns)
parent = parent.returns.items || parent.returns;

@@ -198,3 +200,3 @@ let currElementsNames = Object.keys(parent.elements);

// FIXME: There is currently no other way but to treat the annotation '@odata.Type' as a type property.
for (let prop of ['type', 'length', 'scale', 'precision', 'srid', '@odata.Type']) {
for (let prop of ['type', 'length', 'scale', 'precision', 'srid', 'default', '@odata.Type']) {
if (fkArtifact[prop] != undefined) {

@@ -201,0 +203,0 @@ foreignKeyElement[prop] = fkArtifact[prop];

@@ -23,6 +23,4 @@ 'use strict';

const { error } = message;
// are we working with structured OData or not
const structuredOData = options.toOdata.odataFormat === 'structured' && options.toOdata.version === 'v4';
// are we working with OData proxies or cross-service refs
const isMultiSchema = structuredOData && ((options.toOdata.odataProxies || options.toOdata.odataXServiceRefs));
const isMultiSchema = options.toOdata.version === 'v4' && (options.toOdata.odataProxies || options.toOdata.odataXServiceRefs);
// collect in this variable all the newly exposed types

@@ -29,0 +27,0 @@ const exposedStructTypes = [];

@@ -100,3 +100,3 @@ 'use strict';

// FIXME: There is currently no other way but to treat the annotation '@odata.Type' as a type property.
for (const prop of ['type', 'length', 'scale', 'precision', 'srid', '@odata.Type']) {
for (const prop of ['type', 'length', 'scale', 'precision', 'srid', 'default', '@odata.Type']) {
if (fkArtifact[prop] != undefined) {

@@ -366,5 +366,6 @@ foreignKeyElement[prop] = fkArtifact[prop];

});
const magicVars = ['$now']
// If the path starts with '$self', this is now redundant (because of flattening) and can be omitted,
// making life easier for consumers
if (result[0] === '$self' && result.length > 1) {
if (result[0] === '$self' && result.length > 1 && !magicVars.includes(result[1])) {
result = result.slice(1);

@@ -371,0 +372,0 @@ }

@@ -448,3 +448,3 @@ // Custom resolve functionality for the CDS compiler

function packageFilter( pkg ) {
return { main: pkg.cds && pkg.cds.main || pkg.main };
return { main: pkg.cds && pkg.cds.main };
}

@@ -451,0 +451,0 @@

{
"name": "@sap/cds-compiler",
"version": "2.1.4",
"version": "2.1.6",
"description": "CDS (Core Data Services) compiler and backends",

@@ -5,0 +5,0 @@ "homepage": "https://cap.cloud.sap/",

@@ -42,3 +42,3 @@ # anno-duplicate-unrelated-layer

## Fix
## How to Fix

@@ -45,0 +45,0 @@ To fix the issue, remove one of the duplicate annotations. Chances are, that

@@ -34,3 +34,3 @@ # check-proper-type-of

## Fix
## How to Fix

@@ -37,0 +37,0 @@ To fix the issue, assign an explicit type to `ViewFoo:calculatedField`.

@@ -28,3 +28,3 @@ # check-proper-type

## Fix
## How to Fix

@@ -31,0 +31,0 @@ To fix the issue, add explicit type information to `MainType`, for example, add

@@ -41,3 +41,3 @@ # extend-repeated-intralayer

## Fix
## How to Fix

@@ -44,0 +44,0 @@ To fix the issue, move extensions for the same artifact into the same extension

@@ -39,3 +39,3 @@ # extend-unrelated-layer

## Fix
## How to Fix

@@ -42,0 +42,0 @@ To fix the issue, move extensions for the same artifact into the same layer,

@@ -43,3 +43,3 @@ # redirected-to-ambiguous

## Fix
## How to Fix

@@ -46,0 +46,0 @@ To fix the issue, you must have the original target only once in your direct

@@ -59,3 +59,3 @@ # redirected-to-unrelated

## Fix
## How to Fix

@@ -62,0 +62,0 @@ To fix the issue, you must redirect the association to an entity that originates

@@ -40,3 +40,3 @@ # rewrite-not-supported

## Fix
## How to Fix

@@ -43,0 +43,0 @@ To fix the issue, you have to provide an explicit ON condition. This can be

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc