@sap/eslint-plugin-cds 2.5.0 → 2.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/README.md +2 -1
  3. package/lib/api/index.js +9 -9
  4. package/lib/conf/all.js +20 -19
  5. package/lib/conf/index.js +10 -10
  6. package/lib/conf/recommended.js +17 -16
  7. package/lib/constants.js +16 -14
  8. package/lib/index.js +17 -11
  9. package/lib/parser.js +90 -82
  10. package/lib/rules/assoc2many-ambiguous-key.js +71 -70
  11. package/lib/rules/auth-no-empty-restrictions.js +16 -15
  12. package/lib/rules/auth-use-requires.js +19 -18
  13. package/lib/rules/auth-valid-restrict-grant.js +49 -46
  14. package/lib/rules/auth-valid-restrict-keys.js +19 -18
  15. package/lib/rules/auth-valid-restrict-to.js +68 -64
  16. package/lib/rules/auth-valid-restrict-where.js +44 -43
  17. package/lib/rules/extension-restrictions.js +69 -0
  18. package/lib/rules/index.js +23 -22
  19. package/lib/rules/latest-cds-version.js +21 -20
  20. package/lib/rules/min-node-version.js +22 -22
  21. package/lib/rules/no-db-keywords.js +21 -27
  22. package/lib/rules/no-dollar-prefixed-names.js +12 -11
  23. package/lib/rules/no-join-on-draft.js +27 -0
  24. package/lib/rules/require-2many-oncond.js +8 -8
  25. package/lib/rules/sql-cast-suggestion.js +13 -12
  26. package/lib/rules/start-elements-lowercase.js +42 -41
  27. package/lib/rules/start-entities-uppercase.js +26 -25
  28. package/lib/rules/valid-csv-header.js +58 -57
  29. package/lib/types.d.ts +1 -0
  30. package/lib/utils/Cache.js +17 -17
  31. package/lib/utils/Colors.js +8 -8
  32. package/lib/utils/createRule.js +172 -153
  33. package/lib/utils/findFuzzy.js +37 -38
  34. package/lib/utils/genDocs.js +224 -242
  35. package/lib/utils/getConfigPath.js +27 -27
  36. package/lib/utils/getConfiguredFileTypes.js +4 -4
  37. package/lib/utils/getFileExtensions.js +3 -3
  38. package/lib/utils/getProjectRootPath.js +25 -0
  39. package/lib/utils/isConfiguredFileType.js +11 -11
  40. package/lib/utils/rules.js +59 -59
  41. package/lib/utils/runRuleTester.js +76 -71
  42. package/package.json +7 -1
  43. package/lib/rules/no-join-on-draft-enabled-entities.js +0 -25
  44. package/lib/utils/createRuleDocs.js +0 -361
  45. package/lib/utils/jsonc.js +0 -1
  46. package/lib/utils/jsoncParser.js +0 -1
package/CHANGELOG.md CHANGED
@@ -6,6 +6,30 @@ This project adheres to [Semantic Versioning](http://semver.org/).
6
6
 
7
7
  The format is based on [Keep a Changelog](http://keepachangelog.com/).
8
8
 
9
+ ## [2.6.1] - 2023-01-26
10
+
11
+ ### Changed
12
+
13
+ - Fixed rule name in ESLint config:all to `@sap/cds/start-elements-lowercase`.
14
+ - Allow expensive rules to be reported when running from ESLint Cli.
15
+ - In _auth-valid-restrict-grant_, only suggest closely related user roles.
16
+ - In _auth-valid-restrict-to_, only suggest `*` if other entries apart from `*` exist.
17
+
18
+ ## [2.6.0] - 2022-09-29
19
+
20
+ ### Changed
21
+
22
+ - Renamed rule `no-join-on-draft-enabled-entities` to `no-join-on-draft`.
23
+ - Expanded list of reserved keywords to check for in rule `no-db-keywords`.
24
+
25
+ ### Added
26
+
27
+ - New `extension-restrictions` rule that validates extension projects' models against restrictions set by the extended SaaS app.
28
+
29
+ ### Fixed
30
+
31
+ - Errors from rules are shown again in the console output
32
+
9
33
  ## [2.5.0] - 2022-08-04
10
34
 
11
35
  ### Changed
package/README.md CHANGED
@@ -1,5 +1,6 @@
1
1
  # @sap/eslint-plugin-cds
2
-
2
+ [![JavaScript Style Guide](https://img.shields.io/badge/code_style-standard-brightgreen.svg)](https://standardjs.com)
3
+ [![Sync Files Workflow](https://github.tools.sap/cap/eslint-plugin-cds/actions/workflows/sync.yml/badge.svg)](https://github.tools.sap/cap/eslint-plugin-cds/actions/workflows/sync.yml)
3
4
 
4
5
  The [ESLint](https://eslint.org) plugin includes a set of recommended [SAP Cloud Application Programming Model (CAP)](https://cap.cloud.sap) model and environment rules. The aim of CDS linting is to catch issues with CDS models and with the environment early. To use this module we recommend to install [@sap/cds-dk](https://www.npmjs.com/package/@sap/cds-dk) globally.
5
6
 
package/lib/api/index.js CHANGED
@@ -1,4 +1,4 @@
1
- "use strict";
1
+ 'use strict'
2
2
 
3
3
  /**
4
4
  * Our custom ESLint plugin API should:
@@ -9,12 +9,12 @@
9
9
  * - Expose 'parserPath' for CDS Lint rule unit tests with ESLint's ruleTester
10
10
  */
11
11
 
12
- const runRuleTester = require("../utils/runRuleTester");
13
- const createRule = require("../utils/createRule");
14
- const genDocs = require("../utils/genDocs");
15
- const getConfigPath = require("../utils/getConfigPath");
16
- const getConfiguredFileTypes = require("../utils/getConfiguredFileTypes");
17
- const parserPath = require.resolve("../parser");
12
+ const runRuleTester = require('../utils/runRuleTester')
13
+ const createRule = require('../utils/createRule')
14
+ const genDocs = require('../utils/genDocs')
15
+ const getConfigPath = require('../utils/getConfigPath')
16
+ const getConfiguredFileTypes = require('../utils/getConfiguredFileTypes')
17
+ const parserPath = require.resolve('../parser')
18
18
 
19
19
  module.exports = {
20
20
  runRuleTester,
@@ -22,5 +22,5 @@ module.exports = {
22
22
  genDocs,
23
23
  getConfigPath,
24
24
  getFileExtensions: getConfiguredFileTypes,
25
- parserPath,
26
- };
25
+ parserPath
26
+ }
package/lib/conf/all.js CHANGED
@@ -1,21 +1,22 @@
1
- "use strict";
1
+ 'use strict'
2
2
 
3
3
  module.exports = {
4
- "@sap/cds/assoc2many-ambiguous-key": 2,
5
- "@sap/cds/auth-no-empty-restrictions": 2,
6
- "@sap/cds/auth-use-requires": 1,
7
- "@sap/cds/auth-valid-restrict-grant": 1,
8
- "@sap/cds/auth-valid-restrict-keys": 1,
9
- "@sap/cds/auth-valid-restrict-to": "warn",
10
- "@sap/cds/auth-valid-restrict-where": "warn",
11
- "@sap/cds/latest-cds-version": "warn",
12
- "@sap/cds/min-node-version": "error",
13
- "@sap/cds/no-db-keywords": "error",
14
- "@sap/cds/no-dollar-prefixed-names": "warn",
15
- "@sap/cds/no-join-on-draft-enabled-entities": "warn",
16
- "@sap/cds/require-2many-oncond": "error",
17
- "@sap/cds/sql-cast-suggestion": "warn",
18
- "@sap/cds/start-elements-uppercase": "warn",
19
- "@sap/cds/start-entities-uppercase": "warn",
20
- "@sap/cds/valid-csv-header": "error"
21
- };
4
+ '@sap/cds/assoc2many-ambiguous-key': 2,
5
+ '@sap/cds/auth-no-empty-restrictions': 2,
6
+ '@sap/cds/auth-use-requires': 2,
7
+ '@sap/cds/auth-valid-restrict-grant': 2,
8
+ '@sap/cds/auth-valid-restrict-keys': 2,
9
+ '@sap/cds/auth-valid-restrict-to': 2,
10
+ '@sap/cds/auth-valid-restrict-where': 2,
11
+ '@sap/cds/latest-cds-version': 2,
12
+ '@sap/cds/min-node-version': 2,
13
+ '@sap/cds/no-db-keywords': 2,
14
+ '@sap/cds/no-dollar-prefixed-names': 2,
15
+ '@sap/cds/no-join-on-draft': 2,
16
+ '@sap/cds/require-2many-oncond': 2,
17
+ '@sap/cds/sql-cast-suggestion': 2,
18
+ '@sap/cds/start-elements-lowercase': 2,
19
+ '@sap/cds/start-entities-uppercase': 2,
20
+ '@sap/cds/valid-csv-header': 2,
21
+ '@sap/cds/extension-restrictions': 2
22
+ }
package/lib/conf/index.js CHANGED
@@ -1,7 +1,7 @@
1
- const { FILES, GLOBALS, PLUGIN_NAME } = require("../constants");
2
- const { parserPath } = require("../api");
1
+ const { FILES, GLOBALS, PLUGIN_NAME } = require('../constants')
2
+ const { parserPath } = require('../api')
3
3
 
4
- function _createConfig(config) {
4
+ function _createConfig (config) {
5
5
  return {
6
6
  root: true,
7
7
  globals: GLOBALS,
@@ -9,14 +9,14 @@ function _createConfig(config) {
9
9
  overrides: [
10
10
  {
11
11
  files: FILES,
12
- parser: parserPath,
13
- },
12
+ parser: parserPath
13
+ }
14
14
  ],
15
- rules: config,
16
- };
15
+ rules: config
16
+ }
17
17
  }
18
18
 
19
19
  module.exports = {
20
- all: _createConfig(require("./all")),
21
- recommended: _createConfig(require("./recommended")),
22
- };
20
+ all: _createConfig(require('./all')),
21
+ recommended: _createConfig(require('./recommended'))
22
+ }
@@ -1,18 +1,19 @@
1
- "use strict";
1
+ 'use strict'
2
2
 
3
3
  module.exports = {
4
- "@sap/cds/assoc2many-ambiguous-key": [2, "hide"],
5
- "@sap/cds/auth-no-empty-restrictions": 2,
6
- "@sap/cds/auth-use-requires": 1,
7
- "@sap/cds/auth-valid-restrict-grant": 1,
8
- "@sap/cds/auth-valid-restrict-keys": 1,
9
- "@sap/cds/auth-valid-restrict-to": 1,
10
- "@sap/cds/auth-valid-restrict-where": 1,
11
- "@sap/cds/min-node-version": 2,
12
- "@sap/cds/no-db-keywords": 2,
13
- "@sap/cds/no-dollar-prefixed-names": 1,
14
- "@sap/cds/no-join-on-draft-enabled-entities": [1, "hide"],
15
- "@sap/cds/require-2many-oncond": 2,
16
- "@sap/cds/sql-cast-suggestion": 1,
17
- "@sap/cds/valid-csv-header": 1
18
- };
4
+ '@sap/cds/assoc2many-ambiguous-key': 2,
5
+ '@sap/cds/auth-no-empty-restrictions': 2,
6
+ '@sap/cds/auth-use-requires': 1,
7
+ '@sap/cds/auth-valid-restrict-grant': 1,
8
+ '@sap/cds/auth-valid-restrict-keys': 1,
9
+ '@sap/cds/auth-valid-restrict-to': 1,
10
+ '@sap/cds/auth-valid-restrict-where': 1,
11
+ '@sap/cds/min-node-version': 2,
12
+ '@sap/cds/no-db-keywords': 1,
13
+ '@sap/cds/no-dollar-prefixed-names': 1,
14
+ '@sap/cds/no-join-on-draft': 1,
15
+ '@sap/cds/require-2many-oncond': 2,
16
+ '@sap/cds/sql-cast-suggestion': 1,
17
+ '@sap/cds/valid-csv-header': 1,
18
+ '@sap/cds/extension-restrictions': 2
19
+ }
package/lib/constants.js CHANGED
@@ -12,25 +12,26 @@
12
12
  * - GLOBALS: Globals which should be exposed to ESLint by this plugin
13
13
  */
14
14
 
15
- const RULE_FLAVORS = ["parsed" , "inferred"];
15
+ const RULE_FLAVORS = ['parsed', 'inferred']
16
16
 
17
- const DEFAULT_RULE_FLAVOR = RULE_FLAVORS[0];
17
+ const DEFAULT_RULE_CATEGORY = 'Model Validation'
18
+ const DEFAULT_RULE_FLAVOR = RULE_FLAVORS[0]
19
+ const DEFAULT_RULE_SEVERITY = 'error'
20
+ const DEFAULT_RULE_TYPE = 'problem'
18
21
 
19
- const DEFAULT_RULE_SEVERITY = "error";
20
- const DEFAULT_RULE_TYPE = "problem";
22
+ const PLUGIN_NAME = require('../package.json').name
21
23
 
22
- const PLUGIN_NAME = require("../package.json").name;
24
+ const PLUGIN_SCOPE = '@sap'
25
+ const PLUGIN_PREFIX = `${PLUGIN_SCOPE}/cds`
26
+ const CUSTOM_RULES_DIR = '.cdslint'
23
27
 
24
- const PLUGIN_SCOPE = "@sap";
25
- const PLUGIN_PREFIX = `${PLUGIN_SCOPE}/cds`;
26
- const CUSTOM_RULES_DIR = ".cdslint";
27
-
28
- const FILES = ["*.cds", "*.csn", "*.csv"];
29
- const MODEL_FILES = ["*.cds", "*.csn"];
28
+ const FILES = ['*.cds', '*.csn', '*.csv']
29
+ const MODEL_FILES = ['*.cds', '*.csn']
30
30
 
31
31
  const GLOBALS = {
32
32
  SELECT: true,
33
33
  INSERT: true,
34
+ UPSERT: true,
34
35
  UPDATE: true,
35
36
  DELETE: true,
36
37
  CREATE: true,
@@ -38,11 +39,12 @@ const GLOBALS = {
38
39
  CDL: true,
39
40
  CQL: true,
40
41
  CXL: true,
41
- cds: true,
42
- };
42
+ cds: true
43
+ }
43
44
 
44
45
  module.exports = {
45
46
  RULE_FLAVORS,
47
+ DEFAULT_RULE_CATEGORY,
46
48
  DEFAULT_RULE_FLAVOR,
47
49
  DEFAULT_RULE_SEVERITY,
48
50
  DEFAULT_RULE_TYPE,
@@ -53,4 +55,4 @@ module.exports = {
53
55
  FILES,
54
56
  MODEL_FILES,
55
57
  GLOBALS
56
- };
58
+ }
package/lib/index.js CHANGED
@@ -1,3 +1,10 @@
1
+ // index.js
2
+ /**
3
+ * ## Plugin structure
4
+ * This is the main entry point of our [custom ESLint plugin](https://eslint.org/docs/developer-guide/working-with-plugins),
5
+ * which exposes sets of [rules]() along with their [severity configurations]() to the [ESLint Cli]() or [API]().
6
+ * @module
7
+ */
1
8
  /**
2
9
  * Custom ESLint plugin:
3
10
  * https://eslint.org/docs/developer-guide/working-with-plugins
@@ -8,16 +15,15 @@
8
15
  * - Expose any 'rules' for use in ESLint
9
16
  */
10
17
 
11
- const api = require("./api");
12
- const rules = Object.assign(
13
- {},
14
- ...Object.entries(require("./rules")).map(([k, v]) => ({
15
- [k]: v() }))
16
- );
17
- const configs = require("./conf");
18
+ const api = require('./api')
19
+ const rules = Object.assign(
20
+ {},
21
+ ...Object.entries(require('./rules')).map(([k, v]) => ({ [k]: v() }))
22
+ )
23
+ const configs = require('./conf')
18
24
 
19
25
  module.exports = {
20
- configs,
21
- rules,
22
- ...api
23
- };
26
+ configs,
27
+ rules,
28
+ ...api
29
+ }
package/lib/parser.js CHANGED
@@ -8,172 +8,180 @@
8
8
  * Both methods should take in the source code and an optional configuration
9
9
  * (parserOptions).
10
10
  */
11
- const cds = require("@sap/cds");
12
- const Cache = require("./utils/Cache");
13
- const LOG = cds.debug("lint:plugin");
14
- const colors = require("./utils/Colors");
11
+ const cds = require('@sap/cds')
12
+ const Cache = require('./utils/Cache')
13
+ const LOG = cds.debug('lint:plugin')
14
+ const colors = require('./utils/Colors')
15
+ const { splitDefName } = require('./utils/rules')
15
16
 
16
17
  module.exports = {
17
18
  parse: function (code, options) {
18
- return module.exports.parseForESLint(code, options).ast;
19
+ return module.exports.parseForESLint(code, options).ast
19
20
  },
20
21
  parseForESLint: function (code) {
21
22
  return {
22
23
  ast: createProgramAST(code),
23
24
  services: {
24
25
  getParsedCsn: function () {
25
- let compiledModel;
26
- let reflectedModel;
27
- const messages = [];
26
+ let compiledModel
27
+ let reflectedModel
28
+ const messages = []
28
29
  try {
29
- compiledModel = cds.parse(code);
30
+ compiledModel = cds.parse(code)
30
31
  } catch (err) {
31
32
  // Do nothing
32
33
  }
33
34
  if (compiledModel) {
34
35
  try {
35
- reflectedModel = cds.linked(compiledModel);
36
+ reflectedModel = cds.linked(compiledModel)
36
37
  if (messages) {
37
- reflectedModel.messages = messages;
38
+ reflectedModel.messages = messages
38
39
  }
39
40
  } catch (err) {
40
- LOG && LOG(colors.red + 'ERROR:' + colors.reset, err)
41
+ LOG && LOG(colors.red + 'ERROR:' + colors.reset, err)
41
42
  LOG && LOG('COMPILED', compiledModel)
42
43
  LOG && LOG('REFLECTED', reflectedModel)
43
44
  }
44
45
  }
45
- return reflectedModel;
46
+ return reflectedModel
46
47
  },
47
- getInferredCsn: function() {
48
- const rootPath = Cache.get(`rootpath`);
49
- if (Cache.has("test")) {
50
- return Cache.get(`model:${rootPath}`);
48
+ getInferredCsn: function () {
49
+ const rootPath = Cache.get('rootpath')
50
+ if (Cache.has('test')) {
51
+ return Cache.get(`model:${rootPath}`)
51
52
  }
52
- let compiledModel;
53
- let reflectedModel;
54
- cds.resolve.cache = {};
53
+ let compiledModel
54
+ let reflectedModel
55
+ cds.resolve.cache = {}
55
56
 
56
- if (!Cache.has(`model:${rootPath}`)) {
57
- const roots = cds.resolve("*", { root: rootPath });
58
- const messages = [];
57
+ if (!Cache.has(`model:${rootPath}`) && rootPath) {
58
+ const roots = Cache.get(`roots:${rootPath}`)
59
+ const messages = []
59
60
  if (roots) {
60
- try {
61
- compiledModel = cds.load(roots, {
62
- cwd: ".",
63
- sync: true,
64
- locations: true,
65
- messages,
66
- });
67
- Cache.remove('errRootModel');
68
- } catch (err) {
69
- Cache.set('errRootModel', err);
70
- }
71
- if (compiledModel) {
72
- reflectedModel = cds.linked(compiledModel);
73
- Cache.set(`model:${Cache.get(`rootpath`)}`, reflectedModel);
74
- if (messages) {
75
- reflectedModel.messages = messages;
76
- }
61
+ try {
62
+ compiledModel = cds.load(roots, {
63
+ cwd: rootPath,
64
+ sync: true,
65
+ locations: true,
66
+ messages
67
+ })
68
+ Cache.remove('errRootModel')
69
+ } catch (err) {
70
+ Cache.set('errRootModel', err)
71
+ }
72
+ if (compiledModel) {
73
+ reflectedModel = cds.linked(compiledModel)
74
+ Cache.set(`model:${Cache.get('rootpath')}`, reflectedModel)
75
+ if (messages) {
76
+ reflectedModel.messages = messages
77
77
  }
78
78
  }
79
+ }
79
80
  } else {
80
- reflectedModel = Cache.get(`model:${rootPath}`);
81
+ reflectedModel = Cache.get(`model:${rootPath}`)
81
82
  }
82
- return reflectedModel;
83
+ return reflectedModel
83
84
  },
84
85
  updateInferredCsn: compileModelFromDict,
85
86
  getEnvironment: function () {
86
- const options = Cache.get("options");
87
+ const options = Cache.get('options')
87
88
  return (options && options[0] && options[0].environment) ? options[0].environment : undefined
88
89
  },
89
- getLocation: function(name, obj, model) {
90
- let loc;
90
+ getLocation: function (name, obj, model) {
91
+ let loc
91
92
  const defaultLoc = {
92
93
  start: { line: 0, column: 0 },
93
- end: { line: 1, column: 0 },
94
- };
94
+ end: { line: 1, column: 0 }
95
+ }
95
96
  if (obj.$location) {
96
- const nameloc = obj.$location;
97
- if (nameloc) {
97
+ const objLoc = obj.$location
98
+ if (objLoc) {
98
99
  // CSN entry with column 0 is equivalent to 'undefined'
99
100
  // It means that the column in that line cannot be determined,
100
101
  // so we assign a value 1 to get a column location of 0
101
- if (nameloc.col === 0) {
102
- nameloc.col = 1;
102
+ if (objLoc.col === 0) {
103
+ objLoc.col = 1
103
104
  }
104
- loc = defaultLoc;
105
- loc.start.column = nameloc.col - 1;
106
- loc.start.line = nameloc.line;
107
- loc.end.column = nameloc.col - 1 + name.length;
108
- loc.end.line = nameloc.line;
105
+ loc = defaultLoc
106
+ loc.start.column = objLoc.col - 1
107
+ loc.start.line = objLoc.line
108
+ let colLength = name?.length // use length of `name` property
109
+ // TODO bug in reflect? : `annotate` elements have an unusable index-like `name`, e.g. "1"
110
+ if (obj.annotate) colLength = 0
111
+ loc.end.column = objLoc.col - 1 + colLength
112
+ loc.end.line = objLoc.line
109
113
  } else if (obj.parent) {
110
- this.getLocation(name, obj.parent, model);
114
+ this.getLocation(name, obj.parent, model)
111
115
  }
112
116
  }
113
117
  // Empty locations default to line 0, column 0
114
118
  if (!loc) {
115
- loc = defaultLoc;
119
+ loc = defaultLoc
116
120
  }
117
- return loc;
121
+ return loc
118
122
  },
119
- getNode: function(obj) {
120
- let loc;
121
- if (obj && obj.name) {
122
- loc = this.getLocation(obj.name, obj);
123
+ getNode: function (obj) {
124
+ let loc
125
+ if (obj) {
126
+ let name = obj.name
127
+ if (['entity', 'service'].includes(obj.kind)) {
128
+ name = splitDefName(obj).name
129
+ }
130
+ loc = this.getLocation(name, obj)
123
131
  }
124
132
  return createProgramAST(code, loc)
125
133
  }
126
134
  },
127
135
  scopeManager: null,
128
136
  tokensAndComments: [],
129
- visitorKeys: [],
130
- };
137
+ visitorKeys: []
138
+ }
131
139
  },
132
140
  createProgramAST,
133
- compileModelFromDict,
134
- };
141
+ compileModelFromDict
142
+ }
135
143
 
136
144
  /**
137
145
  * Generates dummy AST with just single Program node
138
146
  * @param code Parse file contents
139
147
  * @returns AST
140
148
  */
141
- function createProgramAST(code, loc) {
149
+ function createProgramAST (code, loc) {
142
150
  loc = loc || {
143
151
  start: {
144
152
  line: 1,
145
- column: 0,
153
+ column: 0
146
154
  },
147
155
  end: {
148
156
  line: 1,
149
- column: 0,
157
+ column: 0
150
158
  }
151
- };
159
+ }
152
160
  return {
153
- type: "Program",
161
+ type: 'Program',
154
162
  body: [],
155
- sourceType: "module",
163
+ sourceType: 'module',
156
164
  tokens: [],
157
165
  comments: [],
158
166
  range: [0, code.length],
159
167
  loc
160
- };
168
+ }
161
169
  }
162
170
 
163
- function compileModelFromDict(dictFiles, options) {
164
- let reflectedModel;
165
- const messages = [];
171
+ function compileModelFromDict (dictFiles, options) {
172
+ let reflectedModel
173
+ const messages = []
166
174
  const compiledModel = cds.compile(dictFiles, {
167
175
  sync: true,
168
176
  locations: true,
169
177
  messages,
170
- ...options,
171
- });
178
+ ...options
179
+ })
172
180
  if (compiledModel) {
173
- reflectedModel = cds.linked(compiledModel);
181
+ reflectedModel = cds.linked(compiledModel)
174
182
  if (messages) {
175
- reflectedModel.messages = messages;
183
+ reflectedModel.messages = messages
176
184
  }
177
185
  }
178
- return reflectedModel;
186
+ return reflectedModel
179
187
  }