Socket
Socket
Sign inDemoInstall

@sap/cds-compiler

Package Overview
Dependencies
3
Maintainers
3
Versions
99
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 1.17.1 to 1.18.2

10

lib/backends.js

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

function toSwagger(model, options) {
const { warning, signal } = alerts(model);
const { warning, error, signal } = alerts(model);

@@ -471,2 +471,10 @@ // In case of API usage the options are in the 'options' argument

options = mergeOptions(model.options, options);
// hide to swagger behind betaMode
if (options.betaMode) {
signal(warning`The to swagger backend is experimental`);
} else {
signal(error`The to swagger backend is only available in beta-mode and is experimental`);
}
// If neither 'json' nor 'csn' is specified as output option, produce 'json'

@@ -473,0 +481,0 @@ if (!options.toSwagger || (!options.toSwagger.json && !options.toSwagger.csn)) {

@@ -46,2 +46,5 @@ // Implementation of alerts

signal.error = error;
signal.warning = warning;
signal.ino = info;
return {

@@ -48,0 +51,0 @@ info, warning, error, // tag functions for the different alerts

@@ -225,2 +225,4 @@ // Functions and classes for syntax messages

arg = arg._artifact;
if (arg._outer)
arg = arg._outer;
let name = arg.name;

@@ -227,0 +229,0 @@ if (!name)

4

lib/base/model.js

@@ -25,6 +25,6 @@ //

// for details.
function forEachMember( construct, callback ) {
function forEachMember( construct, callback, target ) {
let obj = construct.returns || construct; // why the extra `returns` for actions?
obj = obj.items || obj;
forEachGeneric( obj, 'elements', callback );
forEachGeneric( target || obj, 'elements', callback );
forEachGeneric( obj, 'enum', callback );

@@ -31,0 +31,0 @@ forEachGeneric( obj, 'foreignKeys', callback );

@@ -376,2 +376,5 @@ 'use strict'

if(options.betaMode && !options.testMode) {
result.push('Option --beta-mode was used. This option should not be used in productive scenarios!')
}
if (options && options.newCsn === false) {

@@ -381,2 +384,12 @@ result.push(`Option --old-csn was used. This option is deprecated and should not be used in productive scenarios!`)

if(options) {
['length', 'precision', 'scale'].forEach(facet => {
if(options[facet] && isNaN(options[facet])) {
result.push(`Invalid value "${options[facet]}" for option "--${facet}" - not an Integer`);
} else {
options[facet] = parseInt(options[facet]);
}
});
}
if (command) {

@@ -383,0 +396,0 @@ let cmd = optionProcessor.commands[command];

@@ -40,5 +40,7 @@ 'use strict';

// FIXME: convenience function (reuse in forHana)?
const context = { EntityhasPersistenceSkipOrTrueOrAbstract: elem._parent.abstract || ((elem._parent['@cds.persistence.skip'] && elem._parent['@cds.persistence.skip'].val !== null && elem._parent['@cds.persistence.skip'].val !== false)|| (elem._parent['@cds.persistence.exists'] && elem._parent['@cds.persistence.exists'].val !== null && elem._parent['@cds.persistence.exists'].val !== false))};
let assocType = isComposition(elem.type) ? "composition" : "association";
signal(warning`The ${assocType} "${elem.name.id}" has cardinality "to many" but no ON-condition`, elem.location, undefined, 'to-many-no-on', context);
if (!process.env.skip_warning_about_assoc_to_many) {
const context = { EntityhasPersistenceSkipOrTrueOrAbstract: elem._parent.abstract || ((elem._parent['@cds.persistence.skip'] && elem._parent['@cds.persistence.skip'].val !== null && elem._parent['@cds.persistence.skip'].val !== false)|| (elem._parent['@cds.persistence.exists'] && elem._parent['@cds.persistence.exists'].val !== null && elem._parent['@cds.persistence.exists'].val !== false))};
let assocType = isComposition(elem.type) ? "composition" : "association";
signal(warning`The ${assocType} "${elem.name.id}" has cardinality "to many" but no ON-condition`, elem.location, undefined, 'to-many-no-on', context);
}
}

@@ -45,0 +47,0 @@ }

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

if (options.toHana) {
// TODO: Clarify when this is needed - only HANA, all transformers, after compile?
// TODO: Fix "options-check" - does not work if no HANA option passed...
checkNotEmptyOrOnlyVirtualElems(art, model);

@@ -114,0 +116,0 @@ }

@@ -121,2 +121,3 @@ // Consistency checker on model (XSN = augmented CSN)

dependencies: { test: TODO }, // TODO: describe
fileDep: { test: TODO },
$frontend: { parser: true, test: isString, enum: [ 'cdl', 'json', 'xml' ] },

@@ -156,3 +157,3 @@ messages: {

requires: [ 'kind', 'location' ],
optional: [ 'name', 'extern', 'usings', 'annotationAssignments' ], // TODO: get rid of annos: []
optional: [ 'name', 'extern', 'usings', 'annotationAssignments', 'fileDep' ], // TODO: get rid of annos: []
},

@@ -260,3 +261,11 @@ extern: {

},
target: { kind: true, inherits: 'type' },
target: {
kind: true,
requires: [ 'location' ],
optional: [
'path', 'elements', '_elementsIndexNo', '_outer',
'scope', '_artifact', '$inferred', // TODO: remove the rest
'calculated', // TODO: remove calculated
],
},
path: {

@@ -263,0 +272,0 @@ test: isArray( pathItem ),

@@ -59,3 +59,5 @@ // The builtin artifacts of CDS

SESSION_USER: {},
// SQL-92: also SYSTEM_USER, just USER (is with parens in HANA SQL), VALUE
SYSTEM_USER: {}, // not in HANA
// SQL92: USER - intentionally omitted (useful element name), most DB have USER()
// SQL-92: USER - intentionally omitted (useful element name), which DB support this?
$user: {

@@ -71,11 +73,3 @@ elements: { id: {}, locale: {} },

// const magicVariablesHana = {
// CURRENT_CONNECTION: {},
// CURRENT_SCHEMA: {},
// CURRENT_TRANSACTION_ISOLATION_LEVEL: {},
// CURRENT_UTCDATE: {},
// CURRENT_UTCTIME: {},
// CURRENT_UTCTIMESTAMP: {},
// SYSUUID: {},
// };
// see lib/render/renderUtil.js for DB-specific magic vars, specified in CAP Cds via function

@@ -82,0 +76,0 @@ function initBuiltins( model ) {

@@ -80,5 +80,6 @@ // Compiler functions and utilities shared across all phases

typeOf: { next: '_$next', assoc: false }, // warn
include: { reject: rejectNonStruct },
context: { reject: rejectNonContext },
target: { reject: rejectNonEntity, noDep: true },
include: { reject: rejectNonStruct, envFn: artifactsEnv },
context: { reject: rejectNonContext, envFn: artifactsEnv },
target: { reject: rejectNonEntity, noDep: true, envFn: artifactsEnv },
compositionTarget: { reject: rejectNonTarget, noDep: true, envFn: artifactsEnv },
// TODO: dep for (explicit+implicit!) foreign keys

@@ -143,2 +144,6 @@ element: { next: '__none_' }, // foreign key element

function rejectNonTarget( art ) {
return (options.betaMode && art.kind === 'type') ? rejectNonStruct( art ) : rejectNonEntity( art );
}
function rejectNonSource( art, path ) {

@@ -675,3 +680,3 @@ if ([ 'view', 'entity' ].includes( art.kind ))

if (prop) { // extension or structure include
// TODO: consider ARRAY OF and RETURNS
// TODO: consider ARRAY OF and RETURNS, COMPOSITION OF type
if (!(prop in parent))

@@ -678,0 +683,0 @@ parent[prop] = Object.create(null);

@@ -158,2 +158,6 @@ 'use strict';

}
if(properties.filter(p => p.isKey).length === 0) {
signal(error`EntityType "${serviceName}/${EntityTypeName}" has no primary key`, ['definitions',entityCsn.name]);
}
// construct EntityType attributes

@@ -356,7 +360,7 @@ let attributes = { Name : EntityTypeName };

// (undefined !== false) still evaluates to true
if (!elementCsn.target.abstract && elementCsn['@odata.navigable'] !== false)
if (!elementCsn._target.abstract && elementCsn['@odata.navigable'] !== false)
{
let navProp = new Edm.NavigationProperty(v, {
Name: elementName,
Type: fullQualified(elementCsn.target.name)
Type: fullQualified(elementCsn._target.name)
}, elementCsn);

@@ -363,0 +367,0 @@

@@ -880,3 +880,3 @@ 'use strict'

_isCollection: this.isToMany(),
_targetCsn: csn.target
_targetCsn: csn._target
} );

@@ -987,3 +987,3 @@

return new NavigationPropertyBinding(this._v,
{ Path: this.Name, Target: this._csn.target.name.replace(namespace, '') }
{ Path: this.Name, Target: this._csn._target.name.replace(namespace, '') }
);

@@ -990,0 +990,0 @@ }

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

if(entityCsn._containerEntity) {
parameterCsn._containerEntity = [];
setProp(parameterCsn, '_containerEntity', []);
for(let c of entityCsn._containerEntity) {

@@ -130,10 +130,10 @@ parameterCsn._containerEntity.push((c==entityCsn.name)?parameterCsn.name:c);

name: parameterToOriginalAssocName,
target: entityCsn,
target: entityCsn.name,
type: 'cds.Association',
_partnerCsn: [],
cardinality: { src: 1, min: 0, max: '*' }
};
setProp(parameterCsn.elements[parameterToOriginalAssocName], '_target', entityCsn);
setProp(parameterCsn.elements[parameterToOriginalAssocName], '_parameterCsn', []);
model.definitions[parameterCsn.name] = parameterCsn;
// modify the original parameter entity with backlink and new name

@@ -147,3 +147,3 @@ entityCsn.name = originalEntityName;

name: backlinkAssocName,
target: parameterCsn,
target: parameterCsn.name,
type: 'cds.Association',

@@ -153,2 +153,4 @@ _partnerCsn: [],

};
setProp(entityCsn.elements[backlinkAssocName], '_target', parameterCsn);
setProp(entityCsn.elements[backlinkAssocName], '_parameterCsn', []);
}

@@ -239,6 +241,6 @@ }

return;
if(typeof element.target === "string") {
if(!element._target) {
let target = model.definitions[element.target];
if(target) {
element.target = target;
setProp(element, '_target', target);
}

@@ -266,8 +268,8 @@ else {

return;
if(typeof element.target === "string") {
if(!element._target) {
throw Error('Expect target to be resolved, parent: ' + struct.name + ', assoc: ' + element.name + ', target: ' + element.target);
}
// in case this is a forward assoc, store the backlink partneres here, _partnerCsn.length > 1 => error
element._partnerCsn = [];
element.target.$proxies = [];
setProp(element, '_partnerCsn', []);
setProp(element._target, '$proxies', []);

@@ -302,16 +304,16 @@ //forward annotations from managed association element to its foreign keys

// (array because the contanee may contained more then once)
if (!element.target._containerEntity) {
element.target._containerEntity = [];
if (!element._target._containerEntity) {
setProp(element._target, '_containerEntity', []);
}
// add container only once per containee
if (!element.target._containerEntity.includes(container.name)) {
element.target._containerEntity.push(container.name);
if (!element._target._containerEntity.includes(container.name)) {
element._target._containerEntity.push(container.name);
// Mark associations in the containee pointing to the container (i.e. to this entity)
for (let containeeElementName in element.target.elements) {
let containeeElement = element.target.elements[containeeElementName];
if (containeeElement.target && containeeElement.target.name) {
for (let containeeElementName in element._target.elements) {
let containeeElement = element._target.elements[containeeElementName];
if (containeeElement._target && containeeElement._target.name) {
// If this is an association that points to a container (but is not by itself contained,
// which would indicate the top role in a hierarchy) mark it with '_isToContainer'
if (containeeElement.target.name == container.name && !containeeElement['@odata.contained']) {
containeeElement._isToContainer = true;
if (containeeElement._target.name == container.name && !containeeElement['@odata.contained']) {
setProp(containeeElement, '_isToContainer', true);
}

@@ -328,3 +330,3 @@ }

if (element._ignore) return;
element._constraints = getReferentialConstraints(element, signal, warning);
setProp(element, '_constraints', getReferentialConstraints(element, signal, warning));

@@ -375,3 +377,3 @@ // only in V2 we must set the target cardinality of the backlink to the forward:

/*
if(element.target['@cds.autoexpose'] === false) {
if(element._target['@cds.autoexpose'] === false) {
// :TODO: Also _ignore foreign keys to association?

@@ -383,3 +385,3 @@ foreach(struct.elements,

element._ignore = true;
signal(info`${element.type.replace('cds.', '')} "${element.name}" excluded, target "${element.target.name}" is annotated '@cds.autoexpose: ${element.target['@cds.autoexpose']}'`,
signal(info`${element.type.replace('cds.', '')} "${element.name}" excluded, target "${element._target.name}" is annotated '@cds.autoexpose: ${element._target['@cds.autoexpose']}'`,
['definitions', struct.name, 'elements', element.name]);

@@ -390,42 +392,52 @@ return;

// if target is outside defining service, create/reuse proxy
if(myServiceName !== whatsMyServiceName(element.target.name)) {
// search for eventually existing proxy
let proxy = element.target.$proxies.filter(p => p.name.startsWith(myServiceName + '.'))[0];
if(!proxy) {
let name = myServiceName + '.' + element.target.name.split('.').join('_') + '_Proxy_0';
proxy = { name, kind: 'entity', $proxy: true, elements: Object.create(null) };
let hasKeys = false;
foreach(element.target.elements, e => e.key, e => {
// :TODO: getFinalBaseType, resolve structs
// Omit associations (no navigation properties)
if (isAssocOrComposition(e.type)) {
e._ignore = true;
}
if(isStructured(e)) {
e._ignore = true;
// parameters/elements
signal(info`Structured types not yet supported as primary keys of proxy entity type "${name}" for unexposed association target "${element.target.name}"`,
if(myServiceName !== whatsMyServiceName(element._target.name)) {
if(options.betaModeProxy) {
// search for eventually existing proxy
let proxy = element._target.$proxies.filter(p => p.name.startsWith(myServiceName + '.'))[0];
if(!proxy) {
let name = myServiceName + '.' + element._target.name.split('.').join('_') + '_Proxy_0';
proxy = { name, kind: 'entity', $proxy: true, elements: Object.create(null) };
let hasKeys = false;
foreach(element._target.elements, e => e.key, e => {
// :TODO: getFinalBaseType, resolve structs
// Omit associations (no navigation properties)
let ignore = false;
if (isAssocOrComposition(e.type)) {
ignore = true;
}
if(isStructured(e)) {
ignore = true;
// parameters/elements
signal(info`Structured types not yet supported as primary keys of proxy entity type "${name}" for unexposed association target "${element._target.name}"`,
['definitions', struct.name, 'elements', element.name]);
}
if(!ignore) {
// clone elements and strip of all annotations
proxy.elements[e.name] = cloneCsn(e);
Object.keys(proxy.elements[e.name]).forEach(k => { if(k[0] === '@') delete proxy.elements[e.name][k] } );
hasKeys = true;
}
});
if(!hasKeys) {
element._ignore = true;
signal(info`Could not create proxy entity type "${name}" for unexposed association target "${element._target.name}", because target has no primary keys`,
['definitions', struct.name, 'elements', element.name]);
return;
}
// clone elements and strip of all annotations
proxy.elements[e.name] = cloneCsn(e);
hasKeys = true;
});
if(!hasKeys) {
element._ignore = true;
delete element.target.$proxies;
signal(info`Could not create proxy entity type "${name}" for unexposed association target "${element.target.name}", because target has no primary keys"`,
signal(info`Created proxy entity type "${name}" for unexposed association target "${element._target.name}"`,
['definitions', struct.name, 'elements', element.name]);
return;
// wire up proxy
model.definitions[name] = proxy;
element._target.$proxies.push(proxy);
}
signal(info`Created proxy entity type "${name}" for unexposed association target "${element.target.name}"`,
element._target = proxy;
// remove referential constraints
element._constraints.constraints = Object.create(null);
}
else {
element._ignore = true;
signal(info`Association is auto-excluded, as target "${element._target.name}" is outside any service`,
['definitions', struct.name, 'elements', element.name]);
// wire up proxy
model.definitions[name] = proxy;
element.target.$proxies.push(proxy);
return;
}
element.target = proxy;
// remove referential constraints
element._constraints.constraints = Object.create(null);
}

@@ -432,0 +444,0 @@ });

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

if(partner) {
let originAssocCsn = assocCsn.target.elements[partner];
let originAssocCsn = assocCsn._target.elements[partner];
if(originAssocCsn == undefined && assocCsn.originalTarget)

@@ -155,4 +155,5 @@ originAssocCsn = assocCsn.originalTarget.elements[partner];

if(originAssocCsn) {
if(originAssocCsn.target != assocCsn._parent) {
signal(warning`"${assocCsn._parent.name}/${assocCsn.name}" references "${originAssocCsn._parent.name}/${partner}" in $self ON condition with target "${originAssocCsn.target.name}"`, ['definitions', parentArtifactName]);
if(originAssocCsn._target != assocCsn._parent) {
isBacklink = false;
signal(warning`"${assocCsn._parent.name}/${assocCsn.name}" references "${originAssocCsn._parent.name}/${partner}" in $self ON condition with target "${originAssocCsn._target.name}"`, ['definitions', parentArtifactName]);
}

@@ -162,3 +163,3 @@ if(isAssociationOrComposition(originAssocCsn)) {

// as they are primary keys of the other entity as well
if(!assocCsn.target.isParamEntity && originAssocCsn.key) {
if(!assocCsn._target.isParamEntity && originAssocCsn.key) {
if(originAssocCsn.keys) {

@@ -196,3 +197,3 @@ for(let fk of originAssocCsn.keys) {

{
signal(warning`Cannot resolve backlink to ${assocCsn.target.name}/${partner}" from "${parentArtifactName}/${assocCsn.name}"`, ['definitions', parentArtifactName]);
signal(warning`Cannot resolve backlink to ${assocCsn._target.name}/${partner}" from "${parentArtifactName}/${assocCsn.name}"`, ['definitions', parentArtifactName]);
}

@@ -206,9 +207,9 @@ }

if(!assocCsn.target.isParamEntity) {
if(!assocCsn._target.isParamEntity) {
// Header is composed of Items => Cds.Composition: Header is principal => use header's primary keys
let dependentEntity = assocCsn._parent;
let principalEntity = assocCsn.target;
let principalEntity = assocCsn._target;
if(assocCsn.type == 'cds.Composition') {
principalEntity = assocCsn._parent;
dependentEntity = assocCsn.target;
dependentEntity = assocCsn._target;
// Swap the constraint elements to be correct on Composition [principal, dependent] => [dependent, principal]

@@ -238,6 +239,6 @@ Object.keys(result.constraints).forEach(cn => {

// FIXME: If path is something structured, perform a path resolution (or use augmented CSN)
if(!assocCsn.target.isParamEntity && assocCsn.keys) {
if(!assocCsn._target.isParamEntity && assocCsn.keys) {
for(let fk of assocCsn.keys) {
let realFk = assocCsn._parent.elements[fk.$generatedFieldName];
let pk = assocCsn.target.elements[fk.ref[0]];
let pk = assocCsn._target.elements[fk.ref[0]];
if(pk && pk.key && !(pk['@cds.api.ignore'] || realFk['@cds.api.ignore']))

@@ -254,3 +255,3 @@ {

// continue with multiplicity
if(assocCsn.target.isParamEntity)
if(assocCsn._target.isParamEntity)
{

@@ -451,2 +452,4 @@ result.constraints = Object.create(null);

}
if(cdsType === 'cds.DecimalFloat' || cdsType === 'cds.hana.SMALLDECIMAL')
signal(signal.warning`"OData V2 does not support ${cdsType}"`, csn.$location);
}

@@ -462,11 +465,12 @@ else // isV4

function addTypeFacets(node, csn, isV2=false)
function addTypeFacets(node, csn)
{
if (csn.length)
const isV2 = node.v2;
if (csn.length !== undefined)
node.MaxLength = csn.length;
if (csn.scale)
if (csn.scale !== undefined)
node.Scale = csn.scale;
else if (csn.type === 'cds.hana.SMALLDECIMAL' && !isV2)
node.Scale = 'floating';
if (csn.precision)
if (csn.precision !== undefined)
node.Precision = csn.precision;

@@ -477,2 +481,6 @@ else if (csn.type === 'cds.hana.SMALLDECIMAL' && !isV2)

node.Precision = 7;
else if(csn.type === 'cds.DecimalFloat' && !isV2) {
node.Scale = 'floating';
node.Precision = 34;
}
// Unicode unused today

@@ -479,0 +487,0 @@ if(csn.unicode)

@@ -44,3 +44,3 @@ // Transform augmented CSN into compact "official" CSN

cardinality: standard, // also for pathItem: after 'id', before 'where'
target: artifactRef,
target,
foreignKeys: renameTo( 'keys', dictAsArray ), // XSN: rename?

@@ -63,3 +63,3 @@ enum: insertOrderDict,

on: (cond) => (typeof cond === 'string' ? undefined : condition( cond )), // also for join
onCond : renameTo( 'on', condition ), // XSN TODO: onCond -> on
onCond : renameTo( 'on', c => (csn_gensrc && c.$inferred) ? undefined : condition(c) ), // XSN TODO: onCond -> on
// definitions, extensions, members ----------------------------------------

@@ -78,3 +78,3 @@ returns: standard, // storing the return type of actions

definitions: sortedDict,
extensions: standard, // is array - TODO: sort
extensions, // is array
messages, // consider compactQuery / compactExpr

@@ -202,6 +202,5 @@ options: ignore,

set( 'definitions', csn, model );
if (!csn_gensrc)
set( 'extensions', csn, model );
else
extensions( csn, model );
const exts = extensions( model.extensions || [], csn, model );
if (exts.length)
csn.extensions = exts;
set( 'messages', csn, model );

@@ -234,5 +233,7 @@ if (model.version)

function extensions( csn, model ) {
let extensions = (model.extensions) ? standard( model.extensions ) : [];
for (let name in model.definitions) {
function extensions( node, csn, model ) {
const exts = node.map( standard ).sort( (a, b) => a.annotate.localeCompare( b.annotate ) );
if (!csn_gensrc)
return exts;
for (let name of Object.keys( model.definitions ).sort()) {
let art = model.definitions[name];

@@ -248,7 +249,6 @@ // in definitions (without redef) with potential inferred elements:

if (Object.keys( annotate ).length > 1)
extensions.push( annotate );
exts.push( annotate );
}
}
if (extensions.length)
csn.extensions = extensions;
return exts;
}

@@ -302,2 +302,11 @@

function target( val ) {
if (!val.elements)
return artifactRef( val, true );
else if (csn_gensrc)
return standard( val )
else
return val._artifact && val._artifact.name.absolute;
}
function elements( dict, csn, node ) {

@@ -510,3 +519,3 @@ if (csn.from) // with SELECT

const magicFunctions = // TODO: calculate from compiler/builtins.js (more with HANA?):
['CURRENT_DATE','CURRENT_TIME','CURRENT_TIMESTAMP','CURRENT_USER','SESSION_USER'];
['CURRENT_DATE','CURRENT_TIME','CURRENT_TIMESTAMP','CURRENT_USER','SESSION_USER','SYSTEM_USER'];
// TODO: quoted magic names like $now should be complained about in the compiler

@@ -614,5 +623,5 @@

const select = { SELECT: standard( node ) };
const elements = node.elements;
if (elements && node._main && node._main.$queries && node !== node._main.$queries[0])
setHidden( select, 'elements', elements );
const elems = node.elements;
if (elems && node._main && node._main.$queries && node !== node._main.$queries[0])
setHidden( select, 'elements', elements( elems, select, node ) );
return addLocation( node.location, select );

@@ -619,0 +628,0 @@ }

@@ -318,3 +318,3 @@ // Error strategy with special handling for (non-reserved) keywords

function intervalSetToArray( recognizer, expected ) {
function intervalSetToArray( recognizer, expected, excludesForNextToken ) {
// similar to `IntervalSet#toTokenString`

@@ -327,6 +327,11 @@ var names = [];

}
if (recognizer.$adaptExpectedToken && recognizer.$nextTokensToken === recognizer.$adaptExpectedToken)
names = names.filter( n => !recognizer.$adaptExpectedExcludes.includes( n ) );
else if (names.includes("';'"))
if (recognizer.$adaptExpectedToken && recognizer.$nextTokensToken === recognizer.$adaptExpectedToken) {
let excludes = (excludesForNextToken && recognizer.$adaptExpectedExcludes[0] instanceof Array)
? recognizer.$adaptExpectedExcludes[0]
: recognizer.$adaptExpectedExcludes;
names = names.filter( n => !excludes.includes( n ) );
}
else if (names.includes("';'")) {
names = names.filter( n => n !== "'}'" );
}
names.sort( (a, b) => tokenPrecedence(a) < tokenPrecedence(b) ? -1 : 1 );

@@ -408,2 +413,3 @@ return names;

expected, lookBusy, calledRules, true, true );
return intervalSetToArray( recognizer, expected, true );
}

@@ -410,0 +416,0 @@ else if (offendingToken && recognizer.$nextTokensContext &&

@@ -48,2 +48,3 @@ // Generic ANTLR parser class with AST-building functions

setMaxCardinality,
handleComposition,
hanaFlavorOnly,

@@ -153,2 +154,5 @@ betaModeOnly,

// Using this function "during ATN decision making" has no effect
// In front of an ATN decision, you might specify dedicated excludes
// for non-LA1 tokens via a sub-array in excludes[0].
function excludeExpected( excludes ) {

@@ -160,2 +164,3 @@ if (excludes) {

this.$nextTokensToken = t;
this.$nextTokensContext = null;
}

@@ -469,11 +474,25 @@ }

function setMaxCardinality( art, token, max ) {
function setMaxCardinality( art, token, max, inferred ) {
let location = this.tokenLocation( token );
if (art.cardinality) {
if (!art.cardinality) {
art.cardinality = { targetMax: Object.assign( {location}, max ), location };
if (inferred)
art.cardinality.$inferred = inferred;
}
else if (!inferred) {
this.message( 'syntax-repeated-cardinality', location, { token: token.text },
'Warning', 'The target cardinality has already been specified - ignored $(TOKEN)' );
}
else {
art.cardinality = { targetMax: Object.assign( {location}, max ), location };
}
function handleComposition( cardinality, isComposition) {
if (isComposition && !cardinality) {
const lt1 = this._input.LT(1).type;
const la2 = this._input.LT(2);
if (la2.text === '{' && (lt1 === this.constructor.MANY || lt1 === this.constructor.ONE))
la2.type = this.constructor.COMPOSITIONofBRACE;
}
const brace1 = (isComposition) ? 'COMPOSITIONofBRACE' : "'{'";
const manyOne = (cardinality) ? ['MANY', 'ONE'] : [];
this.excludeExpected( [["'}'", 'COMPOSITIONofBRACE'], brace1, ...manyOne] );
}

@@ -480,0 +499,0 @@

@@ -65,3 +65,3 @@ // Main entry point for the Research Vanilla CDS Compiler

const extensions = ['.cds', '.json'];
const extensions = ['.cds', '.csn', '.csn.json', '.json'];

@@ -68,0 +68,0 @@ function packageFilter( pkg ) {

@@ -274,8 +274,8 @@ // CSN functionality for resolving references

for (const prop of csnPath) {
if (isName) { // name/index of artifact/member
isName = false;
if (isName !== 'args') {
if (isName || typeof prop !== 'string') { // array item, name/index of artifact/member, (named) argument
if (typeof isName === 'string') {
parent = art;
art = obj[ prop ];
}
isName = false;
}

@@ -287,3 +287,3 @@ else if (artifactProperties.includes( prop )) {

else if (prop === 'args') {
isName = prop;
isName = true; // for named arguments
if (scope === 'orderBy')

@@ -302,10 +302,11 @@ scope = 'orderBy-xpr'; // no need to extra 'orderBy-args'

}
else if (typeof prop === 'string') {
if (prop !== 'xpr')
scope = prop;
else if (scope === 'orderBy')
scope = 'orderBy-xpr';
else if (prop !== 'xpr') {
scope = prop;
}
else if (scope === 'orderBy') {
scope = 'orderBy-xpr';
}
obj = obj[ prop ];
}
// console.log( 'CPATH:', csnPath, scope, obj );
return { obj, parent, query, scope };

@@ -312,0 +313,0 @@ }

@@ -499,3 +499,3 @@ 'use strict'

let dictObj = dict[name];
if (dictObj instanceof Array) // redefinitions
if (dictObj instanceof Array) // redefinitions - not in CSN!
dictObj.forEach( (o) => callback( o, name, prop, path.concat([prop, name])) )

@@ -502,0 +502,0 @@ else

@@ -31,2 +31,5 @@ const { createOptionProcessor } = require('./base/optionProcessorHelper');

.option(' --old-localized-conv')
.option('--precision <prec>')
.option('--scale <scale>')
.option('--length <length>')
.help(`

@@ -55,2 +58,7 @@ Usage: cdsc <command> [options] <file...>

Type options
--precision <prec> Default precision for 'cds.Decimal'
--scale <scale> Default scale for 'cds.Decimal'
--length <length> Default 'length' for 'cds.String'
Diagnostic options

@@ -57,0 +65,0 @@ --trace-parser Trace parser

@@ -0,3 +1,35 @@

// Common render functions for toCdl.js and toSql.js
const functionsWithoutParams = {
hana: {
CURRENT_CONNECTION: {},
CURRENT_SCHEMA: {},
CURRENT_TRANSACTION_ISOLATION_LEVEL: {},
CURRENT_UTCDATE: {},
CURRENT_UTCTIME: {},
CURRENT_UTCTIMESTAMP: {},
SYSUUID: {},
}
}
// Dialect = 'hana' (only relevance at the moment) | 'cap' | 'sqlite'
function renderFunc( node, dialect, renderArgs, parenNameToUpper = false ) {
if (funcWithoutParen( node, dialect ))
return node.func;
else
// unclear why we transform the function name to uppercase in SQL, but only with parentheses
return `${parenNameToUpper ? node.func.toUpperCase() : node.func}(${renderArgs( node.args )})`;
}
function funcWithoutParen( node, dialect ) {
if (!node.args)
return true;
if (!Array.isArray( node.args ) || node.args.length)
return false;
const specials = functionsWithoutParams[dialect];
return specials && specials[node.func.toUpperCase()];
}
/**
* Get the $location from an object and make it look like the XSN location
* Get the $location from an object and make it look like the XSN location - delete - not necessary
*

@@ -21,3 +53,4 @@ * @param {any} location

module.exports = {
renderFunc,
transformLocation
}
}

@@ -10,3 +10,3 @@ "use strict";

const alerts = require('../base/alerts');
const { transformLocation } = require('./renderUtil');
const { transformLocation, renderFunc } = require('./renderUtil'); // TODO: transformLocation should not be necessary
const DuplicateChecker = require('./DuplicateChecker');

@@ -484,8 +484,10 @@

// One join operation, possibly with ON-condition
// FIXME: Clarify if join operators can be n-ary (assuming binary here)
let result = `(${renderViewSource(source.args[0], env)} ${source.join} join ${renderViewSource(source.args[1], env)}`;
if (source.on) {
result += ` on ${renderExpr(source.on, env)}`;
let result = `${renderViewSource(source.args[0], env)}`;
for (let i = 1; i < source.args.length; i++) {
result = `(${result} ${source.join} join ${renderViewSource(source.args[i], env)}`;
if (source.on) {
result += ` on ${renderExpr(source.on, env)}`;
}
result += `)`;
}
result += `)`;
return result;

@@ -1008,6 +1010,3 @@ }

else if (x.func) {
if (x.args)
return `${x.func}(${renderArgs(x.args, '=>', env)})`;
else
return x.func;
return renderFunc( x, (options.forHana ? 'hana' : 'cap'), a => renderArgs(a, '=>', env) );
}

@@ -1014,0 +1013,0 @@ // Nested expression

@@ -10,2 +10,3 @@

const version = require('../../package.json').version;
const { renderFunc } = require('./renderUtil'); // TODO: transformLocation should not be necessary
const DuplicateChecker = require("./DuplicateChecker");

@@ -434,8 +435,10 @@

// One join operation, possibly with ON-condition
// FIXME: Clarify if join operators can be n-ary (assuming binary here)
let result = `(${renderViewSource(artifactName, source.args[0], env)} ${source.join.toUpperCase()} JOIN ${renderViewSource(artifactName, source.args[1], env)}`;
if (source.on) {
result += ` ON ${renderExpr(source.on, env)}`;
let result = `${renderViewSource(artifactName, source.args[0], env)}`;
for (let i = 1; i < source.args.length; i++) {
result = `(${result} ${source.join.toUpperCase()} JOIN ${renderViewSource(artifactName, source.args[i], env)}`
if (source.on) {
result += ` ON ${renderExpr(source.on, env)}`;
}
result += `)`;
}
result += `)`;
return result;

@@ -920,6 +923,3 @@ }

else if (x.func) {
if (x.args)
return `${x.func.toUpperCase()}(${renderArgs(x.args, '=>', env)})`;
else
return x.func;
return renderFunc( x, options.toSql.dialect, a => renderArgs(a, '=>', env), true );
}

@@ -926,0 +926,0 @@ // Nested expression

@@ -5,3 +5,3 @@ const schemaObjects = require('./swaggerSchemaObjects');

const { compactSorted } = require('../json/compactor');
const { compactModel } = require('../json/to-csn')
const { compactModel } = require('../json/to-csn');
let swaggerJson = null;

@@ -8,0 +8,0 @@

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

const { CompilationError, hasErrors, sortMessages } = require('../base/messages');
const { isManagedAssociationElement, isStructuredElement, isAssociation, isComposition, isAssocOrComposition, isElementWithType,
const { isManagedAssociationElement, isStructuredElement, isAssociation, isAssocOrComposition, isElementWithType,
renameAnnotation, addBoolAnnotationTo, addStringAnnotationTo, addRefAnnotationTo, copyAnnotations,

@@ -221,6 +221,2 @@ foreachPath, hasBoolAnnotation, getElementDatabaseNameOf, getArtifactDatabaseNameOf } = require('../model/modelUtils');

checkForeignKeys(elem);
if(options.betaMode && isComposition(elem.type) &&
options.toOdata.version == 'v4' &&
!hasBoolAnnotation(elem, '@odata.contained'))
elem['@odata.contained'] = { val: true };
}

@@ -227,0 +223,0 @@

@@ -95,3 +95,2 @@ 'use strict';

isAssociation,
isComposition,
isStructured,

@@ -278,7 +277,2 @@ hasBoolAnnotation,

checkForeignKeys(elem, elemName, defName);
if(options.betaMode &&
isComposition(elem.type) &&
options.toOdata.version == 'v4' &&
elem['@odata.contained'] === undefined)
elem['@odata.contained'] = true;
}

@@ -285,0 +279,0 @@

@@ -18,2 +18,3 @@ 'use strict';

return {
addDefaultTypeFacets,
flattenForeignKeys,

@@ -44,2 +45,19 @@ createForeignKeyElement,

// Try to apply length, precision, scale from options if no type facet is set on the primitive types 'cds.String' or 'cds.Decimal'.
// If 'obj' has primitive type 'cds.String' and no length (and it was not previously a UUID), add default length 5000 if no option is available.
// if 'obj' has primitive type 'cds.Decimal' and no precision or scale try to apply precision, scale from options if available.
function addDefaultTypeFacets(element) {
if (element && element.type && element.type._artifact && !element.type._artifact.name.$renamed) {
if(element.type._artifact.name.absolute == 'cds.String' && element.length === undefined) {
element.length = { literal: 'number', val: (model.options && model.options.length ? model.options.length : 5000) }
}
if(element.type._artifact.name.absolute == 'cds.Decimal' && element.precision === undefined && model.options.precision) {
element.precision = { literal: 'number', val: model.options.precision }
}
if(element.type._artifact.name.absolute == 'cds.Decimal' && element.scale === undefined && model.options.scale) {
element.scale = { literal: 'number', val: model.options.scale }
}
}
}
// For a dictionary `foreignKeys` of foreign key infos, return a dictionary in flattened form, i.e.

@@ -46,0 +64,0 @@ // replace all foreign keys that are managed associations themselves by their respective foreign keys,

@@ -32,2 +32,3 @@ 'use strict';

return {
addDefaultTypeFacets,
flattenForeignKeys,

@@ -61,2 +62,21 @@ createForeignKeyElement,

// Try to apply length, precision, scale from options if no type facet is set on the primitive types 'cds.String' or 'cds.Decimal'.
// If 'obj' has primitive type 'cds.String' and no length try to apply length from options if available or set to default 5000.
// if 'obj' has primitive type 'cds.Decimal' try to apply precision, scale from options if available.
function addDefaultTypeFacets(element) {
if(!element || !element.type)
return;
if (element.type === 'cds.String' && element.length === undefined) {
element.length = model.options && model.options.length ? model.options.length : 5000;
}
if(element.type === 'cds.Decimal' && element.precision === undefined && model.options.precision) {
element.precision = model.options.precision;
}
if(element.type === 'cds.Decimal' && element.scale === undefined && model.options.scale) {
element.scale = model.options.scale;
}
}
// For an array `keys` of foreign key infos, return an array in flattened form

@@ -165,3 +185,4 @@ // in one of the two cases:

copyAnnotations(assoc, foreignKeyElement, true);
if (model.options && !model.options.forHana)
copyAnnotations(assoc, foreignKeyElement, true);

@@ -168,0 +189,0 @@ // If the association is non-fkArtifact resp. key, so should be the foreign key field

{
"name": "@sap/cds-compiler",
"version": "1.17.1",
"version": "1.18.2",
"lockfileVersion": 1,

@@ -5,0 +5,0 @@ "requires": true,

@@ -1,1 +0,1 @@

{"bin":{"cdsc":"bin/cdsc.js","cdshi":"bin/cdshi.js","cdsse":"bin/cdsse.js"},"bundleDependencies":false,"dependencies":{"antlr4":"4.7.1","resolve":"1.8.1","sax":"1.2.4"},"deprecated":false,"description":"CDS (Core Data Services) compiler and backends","keywords":["CDS"],"main":"lib/main.js","name":"@sap/cds-compiler","version":"1.17.1","license":"SEE LICENSE IN developer-license-3.1.txt"}
{"bin":{"cdsc":"bin/cdsc.js","cdshi":"bin/cdshi.js","cdsse":"bin/cdsse.js"},"bundleDependencies":false,"dependencies":{"antlr4":"4.7.1","resolve":"1.8.1","sax":"1.2.4"},"deprecated":false,"description":"CDS (Core Data Services) compiler and backends","keywords":["CDS"],"main":"lib/main.js","name":"@sap/cds-compiler","version":"1.18.2","license":"SEE LICENSE IN developer-license-3.1.txt"}

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 not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

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

Sorry, the diff of this file is not supported yet

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 not supported yet

SocketSocket SOC 2 Logo

Product

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

Packages

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc