@sap/cds-dk 4.5.4 → 4.6.4

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 (48) hide show
  1. package/CHANGELOG.md +61 -0
  2. package/bin/bind.js +124 -8
  3. package/bin/cds-ts.js +1 -1
  4. package/bin/cds.js +1 -0
  5. package/bin/compile/index.js +2 -1
  6. package/bin/env.js +50 -9
  7. package/bin/help.js +1 -0
  8. package/bin/import.js +34 -14
  9. package/bin/repl.js +6 -2
  10. package/bin/watch.js +40 -10
  11. package/lib/bind/bindingResolver.js +138 -0
  12. package/lib/bind/cfKeyProvider.js +353 -0
  13. package/lib/bind/userCdsrcJsonStorageProvider.js +144 -0
  14. package/lib/client/activate.js +3 -9
  15. package/lib/client/auth_manager.js +4 -4
  16. package/lib/client/extend.js +4 -9
  17. package/lib/client/settings_manager.js +6 -5
  18. package/lib/import/common.js +10 -1
  19. package/lib/import/importapi.js +4 -3
  20. package/lib/import/index.js +37 -7
  21. package/lib/import/message.js +1 -0
  22. package/lib/import/utils/MetadataConverter.js +25 -4
  23. package/lib/import/utils/MetadataConverterFactory.js +1 -2
  24. package/lib/import/utils/MultiMap.js +26 -0
  25. package/lib/import/v2parser.js +138 -16
  26. package/lib/import/v4parser.js +212 -172
  27. package/lib/init/constants.js +1 -1
  28. package/lib/init/template/data/index.js +11 -1
  29. package/lib/init/template/hana/index.js +16 -20
  30. package/lib/init/template/lint/files/.eslint/rules/no-entity-moo.js +36 -52
  31. package/lib/init/template/lint/files/.eslint/tests/no-entity-moo/rule.test.js +15 -0
  32. package/lib/init/template/lint/index.js +19 -17
  33. package/lib/init/template/mta/files/mta.yaml.hbs +0 -7
  34. package/lib/init/template/mta/projectReader.js +1 -3
  35. package/lib/init/template/mtx/files/xs-security.json.hbs +3 -1
  36. package/lib/init/template/mtx/package/dependencies.package.json +1 -1
  37. package/lib/init/template/nodejs/files/.gitignore.hbs +1 -0
  38. package/lib/init/template/samples/index.js +1 -1
  39. package/lib/init/template/templateBase.js +10 -41
  40. package/lib/init/util/commandUtil.js +5 -0
  41. package/lib/lint/Linter.js +19 -28
  42. package/lib/lint/generators.js +5 -4
  43. package/lib/lint/io.js +76 -51
  44. package/lib/util/term.js +2 -0
  45. package/lib/watch/node-watch.js +38 -19
  46. package/npm-shrinkwrap.json +1053 -1279
  47. package/package.json +3 -3
  48. package/lib/init/template/lint/files/.eslint/tests/no-entity-moo/test.js +0 -10
@@ -13,8 +13,6 @@ const { nullLogger } = require('../../util/logger');
13
13
  module.exports = class HanaTemplate extends TemplateBase {
14
14
  constructor(projectPath, generator) {
15
15
  super(projectPath, generator, __dirname);
16
-
17
- this.env = null;
18
16
  }
19
17
 
20
18
  async checkEnabled() {
@@ -22,11 +20,11 @@ module.exports = class HanaTemplate extends TemplateBase {
22
20
  return true;
23
21
  }
24
22
 
25
- this.env = await this.getEnv(true);
23
+ const env = await this.getEnv();
26
24
 
27
- const hdiConfigPath = path.join(this.projectPath, this.env.folders.db, 'src/.hdiconfig');
25
+ const hdiConfigPath = path.join(this.projectPath, env.folders.db, 'src/.hdiconfig');
28
26
  if (await this.fsUtil.pathExists(hdiConfigPath)) {
29
- const configFilePath = path.join(this.env.folders.db, 'src/.hdiconfig');
27
+ const configFilePath = path.join(env.folders.db, 'src/.hdiconfig');
30
28
  throw new Error(`Database config file ${configFilePath} already exists. Use --force to overwrite.`);
31
29
  }
32
30
 
@@ -34,22 +32,20 @@ module.exports = class HanaTemplate extends TemplateBase {
34
32
  }
35
33
 
36
34
  // read env from project
37
- async getEnv(force) {
35
+ async getEnv() {
38
36
  const cdsEnvVar = process.env.CDS_ENV;
39
37
  process.env.CDS_ENV = 'production'
40
- let env
41
38
  try {
42
- env = await super.getEnv(force);
39
+ return await super.getEnv();
43
40
  } finally {
44
41
  cdsEnvVar ? process.env.CDS_ENV = cdsEnvVar : delete process.env.CDS_ENV
45
42
  }
46
- return env
47
43
  }
48
44
 
49
45
  async run() {
50
- this.env = await this.getEnv(true);
46
+ const env = await this.getEnv();
51
47
 
52
- await this.templateUtil.copyFiles('common', path.join(this.projectPath, this.env.folders.db), {
48
+ await this.templateUtil.copyFiles('common', path.join(this.projectPath, env.folders.db), {
53
49
  projectName: this.projectName
54
50
  }, this.options.force);
55
51
 
@@ -57,13 +53,13 @@ module.exports = class HanaTemplate extends TemplateBase {
57
53
  const projectType = await this.getProjectType();
58
54
  switch (projectType) {
59
55
  case PROJECT_TYPE.java:
60
- await this.templateUtil.copyFiles('java', path.join(this.projectPath, this.env.folders.db), {}, this.options.force);
56
+ await this.templateUtil.copyFiles('java', path.join(this.projectPath, env.folders.db), {}, this.options.force);
61
57
  await this._updatePomXml();
62
- await this._updateCdsrcJson(cdsrcJsonPath, this.env.folders.db);
58
+ await this._updateCdsrcJson(cdsrcJsonPath, env.folders.db, env);
63
59
  break;
64
60
 
65
61
  case PROJECT_TYPE.nodejs:
66
- await this._updatePackageJson(path.join(this.projectPath, 'package.json'), this.env.folders.db);
62
+ await this._updatePackageJson(path.join(this.projectPath, 'package.json'), env.folders.db, env);
67
63
  break;
68
64
 
69
65
  default: break;
@@ -87,7 +83,7 @@ module.exports = class HanaTemplate extends TemplateBase {
87
83
  }
88
84
  }
89
85
 
90
- async _updatePackageJson(packageJsonPath, modelName) { //NOSONAR
86
+ async _updatePackageJson(packageJsonPath, modelName, env) { //NOSONAR
91
87
  modelName = path.basename(modelName);
92
88
 
93
89
  if (!await this.fsUtil.pathExists(packageJsonPath)) {
@@ -109,7 +105,7 @@ module.exports = class HanaTemplate extends TemplateBase {
109
105
  changed = true
110
106
  }
111
107
 
112
- if (!this._isUsingHana(modelName)) {
108
+ if (!this._isUsingHana(modelName, env)) {
113
109
  packageJson.cds = packageJson.cds || {};
114
110
  packageJson.cds.requires = packageJson.cds.requires || {};
115
111
  packageJson.cds.requires[modelName] = packageJson.cds.requires[modelName] || {};
@@ -130,7 +126,7 @@ module.exports = class HanaTemplate extends TemplateBase {
130
126
  }
131
127
  }
132
128
 
133
- async _updateCdsrcJson(cdsrcJsonPath, modelName) {
129
+ async _updateCdsrcJson(cdsrcJsonPath, modelName, env) {
134
130
  modelName = path.basename(modelName);
135
131
 
136
132
  let changed;
@@ -143,7 +139,7 @@ module.exports = class HanaTemplate extends TemplateBase {
143
139
 
144
140
  this.logger.isDebug && this.logger.debug(`_updateCdsrcJson before: ${JSON.stringify(cdsrcJson, null, 2)}`);
145
141
 
146
- if (!this._isUsingHana(modelName)) {
142
+ if (!this._isUsingHana(modelName, env)) {
147
143
  cdsrcJson.requires = cdsrcJson.requires || {};
148
144
  cdsrcJson.requires[modelName] = cdsrcJson.requires[modelName] || {};
149
145
  cdsrcJson.requires[modelName].kind = KIND_SQL;
@@ -161,7 +157,7 @@ module.exports = class HanaTemplate extends TemplateBase {
161
157
  }
162
158
  }
163
159
 
164
- _isUsingHana(db) {
165
- return this.env.get(`requires.${db}.kind`) === KIND_HANA || this.env.get(`requires.${db}.dialect`) === KIND_HANA || this.env.get(`requires.${db}.use`) === KIND_HANA;
160
+ _isUsingHana(db, env) {
161
+ return env.get(`requires.${db}.kind`) === KIND_HANA || env.get(`requires.${db}.dialect`) === KIND_HANA || env.get(`requires.${db}.use`) === KIND_HANA;
166
162
  }
167
163
  }
@@ -1,56 +1,40 @@
1
- const cdsLint = require("@sap/eslint-plugin-cds/lib/api");
2
-
3
- module.exports = cdsLint.createRule(
4
- // Rule meta data
5
- {
1
+ module.exports = require("@sap/eslint-plugin-cds/lib/api").createRule({
2
+ meta: {
6
3
  docs: {
7
- description: `Demonstrates how to implement a model validation check. This check does not allow any entities named 'Moo'.
8
-
9
- ________________________
10
- < No entity Moo allowed! >
11
- ------------------------
12
- \ ^__^
13
- \ (oo)\_______
14
- (__)\ )\/\
15
- ||----w |
16
- || ||`,
17
- category: "Model Validation",
4
+ description: `Demonstrates how to implement a model validation check.
5
+
6
+ __________________-_______
7
+ < Entity 'Moo' not allowed! >
8
+ --------------------------
9
+ \ ^__^
10
+ \ (oo)\_______
11
+ (__)\ )\/\
12
+ ||----w |
13
+ || ||`,
14
+ version: "1.0.0",
18
15
  },
19
16
  fixable: "code",
20
- type: "problem",
21
- version: "1.0.0",
22
17
  },
23
-
24
- // Rule (cds) logic
25
- (cds, context) => {
26
- let report = [];
27
-
28
- const filepath = context.getFilename();
29
- if (filepath.endsWith(".cds")) {
30
- // Always get model CSN from 'cds.model'
31
- const m = cds.reflect(cds.model);
32
-
33
- // Browse all entities of reflected model
34
- m.forall("entity", (d) => {
35
- // strip namespace from entity, assuming its name doesn't contain dots
36
- const entityName = d.name.split('.').pop()
37
-
38
- // If entity name is "Moo"
39
- if (entityName === "Moo") {
40
-
41
- // Get ESLint properties $loc
42
- const loc = cds.getLocation(entityName, d);
43
- const sourcecode = context.getSourceCode();
44
-
45
- // Apply fix by changing "Moo" to "Moon"
46
- const fix = (fixer) => {
47
- const rangeEnd = sourcecode.getIndexFromLoc({line: loc.end.line, column: loc.end.column});
48
- return fixer.insertTextAfterRange([0, rangeEnd], "n");
49
- };
50
- report.push({ message: "Entity 'Moo' not allowed!", loc, fix, file: d.$location.file });
51
- }
52
- });
53
- return report;
54
- }
55
- }
56
- );
18
+ create: function (context) {
19
+ const m = context.cds.model;
20
+ m.forall("entity", (d) => {
21
+ const entityName = d.name.split(".").pop();
22
+ if (entityName === "Moo") {
23
+ const loc = context.cds.getLocation(entityName, d);
24
+ const fix = (fixer) => {
25
+ const rangeEnd = context.sourcecode.getIndexFromLoc({
26
+ line: loc.end.line,
27
+ column: loc.end.column,
28
+ });
29
+ return fixer.insertTextAfterRange([0, rangeEnd], "n");
30
+ };
31
+ context.report({
32
+ message: "Entity 'Moo' not allowed!",
33
+ loc,
34
+ fix,
35
+ file: d.$location.file,
36
+ });
37
+ }
38
+ });
39
+ },
40
+ })
@@ -0,0 +1,15 @@
1
+ const { runRuleTester } = require("@sap/eslint-plugin-cds/lib/api");
2
+
3
+ runRuleTester({
4
+ root: __dirname,
5
+ filename: "schema.cds",
6
+ errors: [
7
+ {
8
+ message: "Entity 'Moo' not allowed!",
9
+ line: 2,
10
+ column: 8,
11
+ endLine: 2,
12
+ endColumn: 11,
13
+ },
14
+ ],
15
+ });
@@ -24,6 +24,7 @@ module.exports = class LintTemplate extends TemplateBase {
24
24
  this.lintType = "local";
25
25
  this.customRuleExample = false;
26
26
  this.missingNpmDependencies = { names: [], msgs: [] };
27
+ this.isTest = false;
27
28
  }
28
29
 
29
30
  async checkEnabled() {
@@ -41,17 +42,16 @@ module.exports = class LintTemplate extends TemplateBase {
41
42
  }
42
43
 
43
44
  async run() {
44
- const cdsdkPath = path.join(__dirname, "../../../..");
45
- const globalPath = path.join(cdsdkPath, "../..");
46
-
47
45
  // Require ESLint v>=7.0.0
48
- this._checkEslint(globalPath);
46
+ if (!this.isTest) {
47
+ this._checkEslint();
48
+ }
49
49
 
50
50
  // To enable custom lint rules ('lint' or 'lint:dev')
51
51
  if (this.lintType === "local") {
52
52
  // Require local ESLint plugin installation and corresponding config
53
53
  this._checkEslintPlugin();
54
- this._addEslintPluginConfig();
54
+ await this._addEslintPluginConfig();
55
55
  // Include custom lint sample rule and test ('lint:dev')
56
56
  if (this.customRuleExample) {
57
57
  // Generate custom lint rules dirs
@@ -66,15 +66,16 @@ module.exports = class LintTemplate extends TemplateBase {
66
66
  // Generate custom lint rules docs
67
67
  await generators.genDocs(this.projectPath);
68
68
  }
69
+
70
+ // Generate VS Code extension settings
71
+ await io.sanitizeVscodeSettings(
72
+ this.projectPath,
73
+ path.join(this.projectPath, ".vscode/settings.json"),
74
+ this.lintType,
75
+ this.customRuleExample
76
+ );
69
77
  }
70
78
 
71
- // Generate VS Code extension settings
72
- await io.sanitizeVscodeSettings(
73
- this.projectPath,
74
- path.join(this.projectPath, ".vscode/settings.json"),
75
- this.lintType,
76
- this.customRuleExample
77
- );
78
79
  }
79
80
 
80
81
  async finalize() {
@@ -101,15 +102,15 @@ module.exports = class LintTemplate extends TemplateBase {
101
102
  this.logger.log("\n");
102
103
  }
103
104
  });
104
-
105
105
  this._promptInstallDependencies(task);
106
106
  }
107
107
  }
108
108
  }
109
+
109
110
  }
110
111
 
111
- _checkEslint(globalPath) {
112
- const eslintCmd = checks.resolveEslint(this.projectPath, globalPath);
112
+ _checkEslint() {
113
+ const eslintCmd = checks.resolveEslint(this.projectPath, '');
113
114
  if (!eslintCmd) {
114
115
  this.missingNpmDependencies["names"].push("eslint");
115
116
  this.missingNpmDependencies["msgs"].push("ESLint v>=7.0.0");
@@ -144,9 +145,10 @@ module.exports = class LintTemplate extends TemplateBase {
144
145
 
145
146
  async _addEslintPluginConfig() {
146
147
  let configPath = getConfigPath(this.projectPath, this.logger);
147
- if (configPath) {
148
- await io.sanitizeEslintConfig(configPath, this.customRuleExample);
148
+ if (!configPath) {
149
+ configPath = path.join(this.projectPath, ".eslintrc");
149
150
  }
151
+ await io.sanitizeEslintConfig(configPath, this.customRuleExample, this.logger);
150
152
  return;
151
153
  }
152
154
 
@@ -38,7 +38,6 @@ modules:
38
38
  {{#cap.isJava}}
39
39
  {{#cap.isMultitenant}}
40
40
  properties:
41
- SAP_JWT_TRUST_ACL: [{"clientid":"*","identityzone":"sap-provisioning"}] # Trust between server and SaaS Manager
42
41
  SPRING_PROFILES_ACTIVE: cloud
43
42
  {{/cap.isMultitenant}}
44
43
  {{^cap.isMultitenant}}
@@ -50,12 +49,6 @@ modules:
50
49
  commands: [ mvn clean package ]
51
50
  build-result: "target/*-exec.[wj]ar"
52
51
  {{/cap.isJava}}
53
- {{#cap.isNodejs}}
54
- {{#cap.isMultitenant}}
55
- properties:
56
- SAP_JWT_TRUST_ACL: [{"clientid":"*","identityzone":"sap-provisioning"}] # Trust between server and SaaS Manager
57
- {{/cap.isMultitenant}}
58
- {{/cap.isNodejs}}
59
52
  {{#cap.hasRequires}}
60
53
  requires:
61
54
  {{#cap.isJava}}
@@ -22,13 +22,11 @@ module.exports = class ProjectReader {
22
22
  async getEnv(profile = 'production') {
23
23
  const cdsEnvVar = process.env.CDS_ENV
24
24
  process.env.CDS_ENV = profile
25
- let env
26
25
  try {
27
- env = await this.template.getEnv(true);
26
+ return await this.template.getEnv();
28
27
  } finally {
29
28
  cdsEnvVar ? process.env.CDS_ENV = cdsEnvVar : delete process.env.CDS_ENV
30
29
  }
31
- return env
32
30
  }
33
31
 
34
32
  get fsUtil() {
@@ -11,7 +11,9 @@
11
11
  ]}
12
12
  ],
13
13
  "authorities": [
14
- "$XSAPPNAME.MtxDiagnose"
14
+ "$XSAPPNAME.MtxDiagnose",
15
+ "$XSAPPNAME.mtdeployment",
16
+ "$XSAPPNAME.mtcallback"
15
17
  ],
16
18
  "role-templates": [
17
19
  {
@@ -3,7 +3,7 @@
3
3
  "@sap/cds-mtx": "^2",
4
4
  "@sap/hana-client": "^2",
5
5
  "@sap/hdi-deploy": "^4",
6
- "@sap/instance-manager": "^2",
6
+ "@sap/instance-manager": "^3",
7
7
  "@sap/xssec": "^3",
8
8
  "passport": "^0"
9
9
  }
@@ -3,6 +3,7 @@ _out
3
3
  *.db
4
4
  connection.properties
5
5
  default-*.json
6
+ .cdsrc-private.json
6
7
  gen/
7
8
  node_modules/
8
9
  target/
@@ -58,7 +58,7 @@ module.exports = class SamplesTemplate extends TemplateBase {
58
58
  }
59
59
 
60
60
  async _addNodejsSamples() {
61
- const folders = (await this.getEnv(true)).folders;
61
+ const folders = (await this.getEnv()).folders;
62
62
  const dbFolder = path.join(this.projectPath, folders.db);
63
63
  await this.templateUtil.copyFiles('nodejs/db', dbFolder, {}, this.options.force);
64
64
 
@@ -1,11 +1,9 @@
1
1
  const path = require('path');
2
- const cds = require('@sap/cds/lib');
2
+ const Config = require('@sap/cds/lib/env');
3
3
 
4
4
  const TemplateUtil = require('../util/templateUtil');
5
- const commandUtil = require('../util/commandUtil');
6
- const { nullLogger } = require('../util/logger');
7
5
 
8
- const { IS_WIN, PROJECT_TYPE } = require('../constants');
6
+ const { PROJECT_TYPE } = require('../constants');
9
7
 
10
8
 
11
9
  module.exports = class TemplateBase {
@@ -43,49 +41,20 @@ module.exports = class TemplateBase {
43
41
  return true;
44
42
  }
45
43
 
46
- getCdsModulePath() {
47
- return path.join(__dirname, '../../../bin/cds.js');
48
- }
49
-
50
44
  /**
51
45
  * calls cds env and caches result
52
46
  * @param {boolean} force, ignore cached value
53
47
  * @returns {object} the current cds env
54
48
  */
55
- async getEnv(force = false) {
56
- if (!this.env || force) {
57
- let projectPath;
58
- if (await this.fsUtil.pathExists(this.projectPath)) {
59
- projectPath = this.projectPath;
60
- } else {
61
- projectPath = this.cwd;
62
- }
63
-
64
- const logger = (this.logger.isDebug ? this.logger : nullLogger);
65
-
66
- let modPath = this.getCdsModulePath();
67
- if (IS_WIN) {
68
- modPath = `"${modPath}"`;
69
- }
70
-
71
- let envJsonOutput = await commandUtil.spawnCommand('node', [modPath, 'env', 'json'], {
72
- cwd: projectPath,
73
- env: process.env
74
- }, logger, true);
75
-
76
- if (envJsonOutput) {
77
- // cheap check to see if json is valid
78
- if (envJsonOutput.indexOf('":') < 0) {
79
- // eslint-disable-next-line no-control-regex
80
- envJsonOutput = envJsonOutput.replace(/'/g, '"').replace(/\s(\w+):\s/g, ' "$1": ').replace(/\x1b\[\w+m/g, '');
81
- }
82
-
83
- this.env = JSON.parse(envJsonOutput);
84
- // env has additional getters and setters
85
- Object.setPrototypeOf(this.env, cds.env.__proto__);
86
- }
49
+ async getEnv() {
50
+ let projectPath;
51
+ if (await this.fsUtil.pathExists(this.projectPath)) {
52
+ projectPath = this.projectPath;
53
+ } else {
54
+ projectPath = this.cwd;
87
55
  }
88
- return this.env;
56
+
57
+ return Config.for('cds', projectPath);
89
58
  }
90
59
 
91
60
  /**
@@ -50,12 +50,17 @@ class CommandUtil {
50
50
  resolve(stdLogBuffer.getResult());
51
51
  } else {
52
52
  const errorLog = errLogBuffer.getResult();
53
+
53
54
  const error = new Error(`${cmd} ${args.join(' ')} failed with code ${code}, ${errorLog}`)
54
55
  // add code ENOENT on Win if command not found
55
56
  if (IS_WIN && errorLog.includes(cmd) && /not recognized/i.exec(errorLog)) {
56
57
  error.code = 'ENOENT';
57
58
  error.path = cmd;
58
59
  }
60
+
61
+ error.errLog = errorLog;
62
+ error.stdLog = stdLogBuffer.getResult();
63
+
59
64
  reject(error);
60
65
  }
61
66
  });
@@ -14,6 +14,8 @@ const {
14
14
  } = require("@sap/eslint-plugin-cds/lib/api");
15
15
 
16
16
  const IS_WIN = os.platform() === "win32";
17
+ const ALLOWED_FILE_EXTENSIONS = getFileExtensions();
18
+
17
19
  class Linter {
18
20
  constructor() {
19
21
  this.eslintCmd = "";
@@ -21,6 +23,7 @@ class Linter {
21
23
  this.eslintCmdOpts = {};
22
24
  this.eslintCmdOptsIndex = 0;
23
25
  this.eslintCmdFileExpr = "";
26
+ this.formatter = false;
24
27
  this.isFile = false;
25
28
  this.help = "";
26
29
  this.debug = "";
@@ -75,7 +78,7 @@ class Linter {
75
78
  this._printHelp();
76
79
  } else {
77
80
  // Determine if case "local" or "global" and resolve plugin accordingly
78
- this._getConfigFileAndSetProjectPath(args);
81
+ await this._getConfigFileAndSetProjectPath(args);
79
82
 
80
83
  if (this.lintType === "local") {
81
84
  await this._addRulePaths();
@@ -88,7 +91,7 @@ class Linter {
88
91
  "rules"
89
92
  );
90
93
  if (overwriteRules) {
91
- this._overwriteRuleSeverities();
94
+ await this._overwriteRuleSeverities();
92
95
  }
93
96
  }
94
97
 
@@ -138,25 +141,14 @@ class Linter {
138
141
 
139
142
  _addExtensions() {
140
143
  // Add CDS file extensions to lint
144
+ const extensions = ALLOWED_FILE_EXTENSIONS.map((ext) => ext.replace('*.', '.'));
141
145
  this.eslintCmdOpts = io.mergeWithUserOpts(
142
146
  this.eslintCmdOpts,
143
147
  "ext",
144
- ".cds,.csn"
145
- );
146
- // Add custom CDS formatter
147
- const formatterPath = this.pluginPath.replace(
148
- "index.js",
149
- "../api/formatter.js"
150
- );
151
- this.eslintCmdOpts = io.mergeWithUserOpts(
152
- this.eslintCmdOpts,
153
- "format",
154
- path.relative(".", formatterPath)
148
+ extensions.join(',')
155
149
  );
156
150
  // Enable colored output
157
- if (process.stdout.isTTY) {
158
- this.eslintCmdOpts = io.mergeWithUserOpts(this.eslintCmdOpts, "color");
159
- }
151
+ this.eslintCmdOpts = io.mergeWithUserOpts(this.eslintCmdOpts, "color");
160
152
  return;
161
153
  }
162
154
 
@@ -186,7 +178,6 @@ class Linter {
186
178
  }
187
179
  }
188
180
  // Only lint file extensions prescribed by plugin
189
- const fileExtensions = getFileExtensions();
190
181
  eslintCmdOpts.push("--ignore-pattern");
191
182
  let ignorePattern = "*.*";
192
183
  if (IS_WIN) {
@@ -195,7 +186,7 @@ class Linter {
195
186
  ignorePattern = `'${ignorePattern}'`;
196
187
  }
197
188
  eslintCmdOpts.push(ignorePattern);
198
- fileExtensions.forEach((ext) => {
189
+ ALLOWED_FILE_EXTENSIONS.forEach((ext) => {
199
190
  eslintCmdOpts.push("--ignore-pattern");
200
191
  ignorePattern = `!${ext}`;
201
192
  if (IS_WIN) {
@@ -212,18 +203,18 @@ class Linter {
212
203
  } else {
213
204
  input = `'${this.eslintCmdFileExpr.join("' '")}'`;
214
205
  }
215
- const eslintCmdSplit = this.eslintCmd.split(" ");
216
- this.eslintCmd = eslintCmdSplit[0];
217
- eslintCmdOpts.unshift(eslintCmdSplit[1]);
218
- eslintCmdOpts.push(input);
219
206
  // Run ESLint with given cmd line options
207
+ // - Show 'eslint' instead of actual eslint cmd ('node .../.eslint.js')
208
+ // - Remove debug flag for printed cmd line
220
209
  if (this.eslintCmdOpts.debug) {
210
+ eslintCmdOpts.splice(eslintCmdOpts.indexOf('--debug'), 1);
221
211
  console.log(
222
- `Linting:\n ${term.info(`${this.eslintCmd} ${eslintCmdOpts.join(' ')}`)}`
212
+ `Linting:\n ${term.info(`eslint ${eslintCmdOpts.concat(input).join(' ')}`)}\n`
223
213
  );
214
+ eslintCmdOpts.push('--debug');
224
215
  }
225
216
  if (!dryRun) {
226
- return commandUtil.spawnCommand(this.eslintCmd, eslintCmdOpts, {
217
+ return commandUtil.spawnCommand(this.eslintCmd, eslintCmdOpts.concat(input), {
227
218
  cwd: process.cwd(),
228
219
  shell: true,
229
220
  stdio: process.env.NODE_ENV === 'test' ? 'pipe' : 'inherit',
@@ -245,7 +236,7 @@ class Linter {
245
236
  return;
246
237
  }
247
238
 
248
- _getConfigFileAndSetProjectPath(args) {
239
+ async _getConfigFileAndSetProjectPath(args) {
249
240
  let input;
250
241
  // Only resolve the first input argument
251
242
  //
@@ -269,7 +260,7 @@ class Linter {
269
260
  this.configPath = this.configGlobalPath;
270
261
  this.lintType === "global";
271
262
  } else {
272
- this.configContents = io.readEslintConfig(this.configPath);
263
+ this.configContents = await io.readEslintConfig(this.configPath);
273
264
  if (this.configContents) {
274
265
  if ("extends" in this.configContents) {
275
266
  this.extendsPlugin = checks.hasEslintConfigContent(
@@ -295,8 +286,8 @@ class Linter {
295
286
  return;
296
287
  }
297
288
 
298
- _overwriteRuleSeverities() {
299
- let configContents = io.readEslintConfig(this.configPath) || {};
289
+ async _overwriteRuleSeverities() {
290
+ let configContents = (await io.readEslintConfig(this.configPath)) || {};
300
291
  let rules = configContents.rules;
301
292
  // Allow recommended plugin rules in cds-dk to be overwritten
302
293
  // by user by adding rule to cmd line (because of precedence)
@@ -3,6 +3,7 @@ const os = require("os");
3
3
  const cp = require("child_process");
4
4
  const path = require("path");
5
5
  const { mkdirp } = require("@sap/cds/lib/utils");
6
+ const term = require("../util/term");
6
7
 
7
8
  const IS_WIN = os.platform() === "win32";
8
9
 
@@ -35,12 +36,12 @@ module.exports = {
35
36
  let cdslintCmd = eslintOpts[0].replace("eslint", "*cds lint*");
36
37
  eslintOpts[0] = `
37
38
  # SYNOPSIS
38
-
39
+
39
40
  ${cdslintCmd} [beta]
40
-
41
+
41
42
  Runs environment checks and/or checks the specified models
42
43
  based on the ESLint framework
43
-
44
+
44
45
  # OPTIONS`;
45
46
  return `${eslintOpts.join("\n ")}\n`;
46
47
  },
@@ -97,7 +98,7 @@ module.exports = {
97
98
  },
98
99
 
99
100
  /**
100
- * Generates custom rules documentation for user
101
+ * Generates custom rules documentation for user
101
102
  * according to contents of rules files
102
103
  * @param {*} projectPath
103
104
  */