@sap/cds-compiler
Version:
CDS (Core Data Services) compiler and backends
119 lines (108 loc) • 3.26 kB
JavaScript
;
// Model agnostic builtins.
// It should not contain any specific to XSN, i.e. neither XSN structures
// nor any other XSN properties.
/**
* Map of propagation rules for annotations.
* Does not include rules for standard propagation of annotations or other properties.
*
* @type {Record<string, string>}
*/
const propagationRules = {
__proto__: null,
'@Analytics.hidden': 'never',
'@Analytics.visible': 'never',
'@cds.autoexpose': 'onlyViaArtifact',
'@cds.autoexposed': 'never',
'@cds.external': 'never',
'@cds.java.this.name': 'onlyViaParent',
'@cds.persistence.calcview': 'never',
'@cds.persistence.exists': 'never',
'@cds.persistence.skip': 'notWithPersistenceTable',
'@cds.persistence.table': 'never',
'@cds.persistence.udf': 'never',
'@cds.redirection.target': 'never',
'@com.sap.gtt.core.CoreModel.Indexable': 'never',
'@fiori.draft.enabled': 'onlyViaArtifact',
'@sql.append': 'never',
'@sql.prepend': 'never',
'@sql.replace': 'never',
'@extension.code': 'never', // for cds-oyster, not security relevant, but convenience
};
/**
* Of the annotations above, only these accept expressions as annotation values.
*/
const acceptsExprValues = {
__proto__: null,
'@extension.code': true,
};
/**
* Checks whether the given absolute path is inside a reserved namespace.
*
* @param {string} absolute
* @returns {boolean}
*/
function isInReservedNamespace( absolute ) {
return absolute === 'cds' || absolute.startsWith( 'cds.' ) &&
!absolute.match( /^cds\.foundation(\.|$)/ ) &&
!absolute.match( /^cds\.outbox(\.|$)/ ) && // Requested by Node runtime
!absolute.match( /^cds\.core(\.|$)/ ) && // Requested by Node runtime
!absolute.match( /^cds\.xt(\.|$)/ ); // Requested by Mtx
}
/**
* Tell if a type is (directly) a builtin type
* Note that in CSN builtins are not in the definition of the model, so we can only
* check against their absolute names. Builtin types are "cds.<something>", i.e. they
* are directly in 'cds', but not for example in 'cds.foundation'.
*
* @param {string|object} type
* @returns {boolean}
*/
function isBuiltinType( type ) {
type = typeof type === 'string' ? type : type?.ref?.[0];
return type && isInReservedNamespace( type );
}
const magicVariables = [
'$user',
'$at',
'$valid',
'$now',
'$tenant',
'$session',
'$draft',
];
/**
* Tell if a name is a magic variable
*
* @param {string} name
* @returns {boolean}
*/
function isMagicVariable( name ) {
return typeof name === 'string' && magicVariables.includes(name);
}
/**
* Properties that are required next to `=` to make an annotation value an actual expression
* and not some foreign structure.
*
* @type {string[]}
*/
const xprInAnnoProperties = [
'ref', 'xpr', 'list', 'literal', 'val',
'#', 'func', 'args', 'SELECT', 'SET',
'cast',
];
/**
* Return whether JSON object `val` is a representation for an annotation expression
*/
function isAnnotationExpression( val ) {
return val?.['='] !== undefined && xprInAnnoProperties.some( prop => val[prop] !== undefined );
}
module.exports = {
propagationRules,
acceptsExprValues,
xprInAnnoProperties,
isInReservedNamespace,
isBuiltinType,
isMagicVariable,
isAnnotationExpression,
};