@sap/cds-dk 8.9.5 → 9.0.5

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 (109) hide show
  1. package/CHANGELOG.md +101 -2012
  2. package/LICENSE +15 -21
  3. package/bin/bind.js +1 -1
  4. package/bin/build.js +35 -37
  5. package/bin/cds.js +13 -30
  6. package/bin/compile/index.js +2 -2
  7. package/bin/debug.js +27 -7
  8. package/bin/deploy/index.js +6 -23
  9. package/bin/deploy/to-hana.js +4 -2
  10. package/bin/help.js +5 -3
  11. package/bin/init.js +1 -1
  12. package/bin/up.js +45 -12
  13. package/bin/watch.js +45 -63
  14. package/lib/bind/cf.js +2 -1
  15. package/lib/bind/k8s.js +2 -2
  16. package/lib/bind/plugin.js +1 -1
  17. package/lib/bind/shared.js +16 -25
  18. package/lib/build/buildTaskEngine.js +26 -10
  19. package/lib/build/buildTaskFactory.js +3 -2
  20. package/lib/build/buildTaskProvider.js +18 -7
  21. package/lib/build/buildTaskProviderFactory.js +35 -13
  22. package/lib/build/constants.js +4 -0
  23. package/lib/build/index.js +1 -1
  24. package/lib/build/plugin.js +89 -54
  25. package/lib/build/plugins/helm/files/subcharts/web-application/Chart.yaml +3 -1
  26. package/lib/build/plugins/helm/files/subcharts/web-application/templates/_helpers.tpl +4 -2
  27. package/lib/build/plugins/helm/files/subcharts/web-application/templates/api-rule.yaml +4 -2
  28. package/lib/build/plugins/helm/files/subcharts/web-application/templates/deployment.yaml +18 -1
  29. package/lib/build/plugins/helm/files/subcharts/web-application/templates/service-binding.yaml +0 -1
  30. package/lib/build/plugins/helm/files/subcharts/web-application/values.schema.json +34 -2
  31. package/lib/build/plugins/helm/files/subcharts/web-application/values.yaml +9 -2
  32. package/lib/build/plugins/helm/index.js +2 -1
  33. package/lib/build/plugins.js +24 -10
  34. package/lib/build/provider/edmxBuildPlugin.js +1 -11
  35. package/lib/build/provider/fiori/index.js +4 -4
  36. package/lib/build/provider/hana/index.js +12 -5
  37. package/lib/build/provider/hana/template/package.json +1 -1
  38. package/lib/build/provider/internalBuildPlugin.js +1 -1
  39. package/lib/build/provider/internalBuildTaskProvider.js +3 -24
  40. package/lib/build/provider/java/index.js +1 -1
  41. package/lib/build/provider/mtx-extension/index.js +15 -8
  42. package/lib/build/provider/nodejs/index.js +28 -6
  43. package/lib/build/util.js +186 -125
  44. package/lib/deploy/index.js +5 -0
  45. package/lib/deploy/to-hana/hana.js +27 -33
  46. package/lib/deploy/to-hana/hdiDeployUtil.js +2 -2
  47. package/lib/import/odata/v2parser.js +34 -3
  48. package/lib/import/openapi/importOpenAPI.js +4 -0
  49. package/lib/index.js +2 -11
  50. package/lib/init/constants.js +1 -2
  51. package/lib/init/merge.js +101 -77
  52. package/lib/init/mvn.js +3 -3
  53. package/lib/init/projectReader.js +1 -1
  54. package/lib/init/template/ams/files/mta.yaml.hbs +6 -1
  55. package/lib/init/template/ams/files/package.json.hbs +1 -1
  56. package/lib/init/template/approuter/files/mta.yaml.hbs +5 -0
  57. package/lib/init/template/cf-manifest/files/manifest.yml.hbs +1 -1
  58. package/lib/init/template/cloud-logging/files/package.json.hbs +3 -3
  59. package/lib/init/template/data/as-json.js +3 -3
  60. package/lib/init/template/dynatrace/files/mta.yaml.hbs +1 -1
  61. package/lib/init/template/dynatrace/files/package.json.hbs +2 -2
  62. package/lib/init/template/dynatrace/index.js +2 -1
  63. package/lib/init/template/enterprise-messaging/files/mta.yaml.hbs +6 -0
  64. package/lib/init/template/enterprise-messaging/index.js +5 -1
  65. package/lib/init/template/extensibility/files/package.json.hbs +1 -1
  66. package/lib/init/template/hana/files/db/package.json +1 -1
  67. package/lib/init/template/hana/files/package.json.hbs +2 -4
  68. package/lib/init/template/hana/index.js +2 -2
  69. package/lib/init/template/handler/index.js +16 -12
  70. package/lib/init/template/helm/index.js +13 -22
  71. package/lib/init/template/helm-unified-runtime/index.js +2 -1
  72. package/lib/init/template/html5-repo/files/values.yaml.hbs +12 -1
  73. package/lib/init/template/html5-repo/index.js +10 -5
  74. package/lib/init/template/http/index.js +1 -1
  75. package/lib/init/template/ias/files/mta.yaml.hbs +1 -1
  76. package/lib/init/template/ias/files/sidecar.package.json.hbs +0 -7
  77. package/lib/init/template/ias/index.js +5 -4
  78. package/lib/init/template/lint/files/package.json +6 -0
  79. package/lib/init/template/lint/index.js +61 -204
  80. package/lib/init/template/mta/files/package.json +1 -1
  81. package/lib/init/template/multitenancy/files/mta.yaml.hbs +2 -2
  82. package/lib/init/template/multitenancy/files/package.json.hbs +1 -1
  83. package/lib/init/template/multitenancy/files/package.sidecar.json.hbs +7 -4
  84. package/lib/init/template/multitenancy/index.js +3 -0
  85. package/lib/init/template/nodejs/files/package.json.hbs +6 -3
  86. package/lib/init/template/postgres/files/package.json.hbs +1 -1
  87. package/lib/init/template/redis/files/package.json.hbs +1 -1
  88. package/lib/init/template/sample/files/app/admin-books/fiori-service.cds +6 -0
  89. package/lib/init/template/sample/files/app/admin-books/webapp/manifest.json +1 -0
  90. package/lib/init/template/sample/files/app/browse/fiori-service.cds +3 -2
  91. package/lib/init/template/sample/files/app/common.cds +0 -11
  92. package/lib/init/template/sqlite/files/package.json +1 -1
  93. package/lib/init/template/toggles/files/package.json.hbs +1 -1
  94. package/lib/init/template/typescript/files/package.json +2 -4
  95. package/lib/init/template/workzone-standard/index.js +2 -0
  96. package/lib/init/template/xsuaa/index.js +2 -6
  97. package/lib/lint/Linter.js +203 -331
  98. package/lib/lint/generators.js +52 -46
  99. package/lib/lint/io.js +77 -289
  100. package/lib/util/fs.js +2 -1
  101. package/lib/util/git.js +1 -1
  102. package/lib/util/glob.js +77 -0
  103. package/lib/watch/livereload-server.js +3 -4
  104. package/lib/watch/node-watch.js +3 -4
  105. package/lib/watch/watched.js +1 -1
  106. package/npm-shrinkwrap.json +200 -858
  107. package/package.json +6 -8
  108. package/readme.md +1 -1
  109. package/lib/lint/checks.js +0 -135
@@ -1,36 +1,36 @@
1
- const os = require("os");
2
- const cp = require("child_process");
3
- const term = require("../util/term");
1
+ const os = require('node:os')
2
+ const cp = require('node:child_process')
3
+ const term = require('../util/term')
4
4
 
5
- const IS_WIN = os.platform() === "win32";
6
-
7
- const REGEX_FLAGS = /--[a-z,a-z-]+[,\s+]\s+/gm;
8
- const REGEX_OPTIONS = /--[a-z,a-z-]+\s[^\s]/gm;
9
- const REGEX_SHORTCUT_MAPPINGS = /\s-[a-zA-Z]+, --[a-zA-Z-]+/gm;
5
+ const IS_WIN = os.platform() === 'win32'
6
+ const REGEX_FLAGS = /--[a-z,a-z-]+[,\s+]\s+/gm
7
+ const REGEX_OPTIONS = /--[a-z,a-z-]+\s[^\s]/gm
8
+ const REGEX_SHORTCUT_MAPPINGS = /\s-[a-zA-Z]+, --[a-zA-Z-]+/gm
10
9
 
11
10
  module.exports = {
12
11
  /**
13
12
  * Generates `cds lint` help string to print when calling `cds lint [-h, --help]`
14
13
  * by getting available options/shortcuts from installed version of ESLint
15
- * @returns `cds lint` help string
14
+ * @param {string} eslintCmd - ESLint command to call
15
+ * @returns {string} `cds lint` help string
16
16
  */
17
17
  genEslintHelp: function (eslintCmd) {
18
- let eslintHelp;
18
+ let eslintHelp
19
19
  try {
20
20
  eslintHelp = cp
21
21
  .execSync(`${eslintCmd} -h`, {
22
22
  cwd: process.cwd(),
23
23
  shell: IS_WIN,
24
- stdio: "pipe",
24
+ stdio: 'pipe',
25
25
  })
26
- .toString();
27
- } catch (err) {
26
+ .toString()
27
+ } catch {
28
28
  console.log(
29
- `${term.error("Cannot call 'eslint -h', install and try again.")}\n`
30
- );
29
+ `${term.error('Cannot call "eslint -h", install and try again.')}\n`
30
+ )
31
31
  }
32
- let eslintOpts = eslintHelp.split("\n");
33
- let cdslintCmd = eslintOpts[0].replace("eslint", "*cds lint*");
32
+ const eslintOpts = eslintHelp.split('\n')
33
+ const cdslintCmd = eslintOpts[0].replace('eslint', '*cds lint*')
34
34
  eslintOpts[0] = `
35
35
  # SYNOPSIS
36
36
 
@@ -39,8 +39,8 @@ module.exports = {
39
39
  Runs environment checks and/or checks the specified models
40
40
  based on the ESLint framework
41
41
 
42
- # OPTIONS`;
43
- return `${eslintOpts.join("\n ")}\n`;
42
+ # OPTIONS`
43
+ return `${eslintOpts.join('\n ')}\n`
44
44
  },
45
45
 
46
46
  /**
@@ -49,38 +49,45 @@ module.exports = {
49
49
  * Shortcut order must match order of [options, flags]
50
50
  * Any options without an shortcut must act as filler (undefined)
51
51
  * until the shortcuts for the flags start
52
- * @param help help string and shortcuts array for `cds lint`
53
- * @param flags help string and shortcuts array for `cds lint`
54
- * @returns `cds lint` allowed options
52
+ * @param {string} help - help string and shortcuts array for `cds lint`
53
+ * @param {string[]} flags help string and shortcuts array for `cds lint`
54
+ * @returns {{
55
+ * help: string,
56
+ * options: string[],
57
+ * shortcuts: string[],
58
+ * flags: string[]
59
+ * }} `cds lint` allowed options
55
60
  */
56
61
  genEslintShortcutsAndOpts: function (help, flags) {
57
62
  const allOptions = help
58
63
  .match(REGEX_OPTIONS)
59
- .map((str) => str.split(' ')[0].trim().replace(",", ""));
64
+ .map((str) => str.split(' ')[0].trim().replace(',', ''))
60
65
  const shortcutMappings = help
61
66
  .match(REGEX_SHORTCUT_MAPPINGS)
62
- .map((str) => str.trim().split(/,\s?/));
63
- let optionsWithShortcuts = [];
64
- let shortcuts = [];
65
- let shortcutsForFlags = [];
66
- shortcutMappings.forEach((m) => {
67
- if (!flags.includes(m[1])) {
68
- optionsWithShortcuts.push(m[1]);
69
- shortcuts.push(m[0]);
67
+ .map((str) => str.trim().split(/,\s?/))
68
+ const optionsWithShortcuts = []
69
+ /** @type {string[]} */
70
+ let shortcuts = []
71
+ const shortcutsForFlags = []
72
+ shortcutMappings.forEach(([short, long]) => {
73
+ if (!flags.includes(long)) {
74
+ optionsWithShortcuts.push(long)
75
+ shortcuts.push(short)
70
76
  } else {
71
- const index = flags.indexOf(m[1]);
72
- flags.splice(index, 1);
73
- flags.unshift(m[1]);
74
- shortcutsForFlags.unshift(m[0]);
77
+ const index = flags.indexOf(long)
78
+ flags.splice(index, 1)
79
+ flags.unshift(long)
80
+ shortcutsForFlags.unshift(short)
75
81
  }
76
- });
77
- const optionsWithoutShortcuts = allOptions.filter((o) => !optionsWithShortcuts.includes(o));
82
+ })
83
+ const optionsWithoutShortcuts = allOptions.filter((o) => !optionsWithShortcuts.includes(o))
78
84
  optionsWithoutShortcuts.forEach(() => {
79
85
  shortcuts.push(undefined)
80
- });
81
- let options = optionsWithShortcuts.concat(optionsWithoutShortcuts);
82
- shortcuts = shortcuts.concat(shortcutsForFlags);
83
- return [help, options, shortcuts, flags];
86
+ })
87
+ /** @type {string[]} */
88
+ const options = optionsWithShortcuts.concat(optionsWithoutShortcuts)
89
+ shortcuts = shortcuts.concat(shortcutsForFlags)
90
+ return [help, options, shortcuts, flags]
84
91
  },
85
92
 
86
93
  /**
@@ -90,8 +97,7 @@ module.exports = {
90
97
  * @param help string from `cds lint [-h, --help]`
91
98
  * @returns ESLint flags
92
99
  */
93
- genEslintFlags: function (help) {
94
- return help.match(REGEX_FLAGS).map((str) => str.trim().replace(",", ""));
95
- }
96
-
97
- };
100
+ genEslintFlags: help => help
101
+ .match(REGEX_FLAGS)
102
+ .map(str => str.trim().replace(',', ''))
103
+ }
package/lib/lint/io.js CHANGED
@@ -1,271 +1,93 @@
1
- const { read, write, exists, yaml } = require('../cds').utils;
2
- const cds = require("../cds");
1
+ const { write, exists } = require('../cds').utils
2
+ const cds = require('../cds')
3
3
 
4
- const { readJSONC } = require("../util/fs");
5
- const path = require("path");
6
- const term = require("../util/term");
7
- const JSONC = require('../util/jsonc');
4
+ const { readJSONC } = require('../util/fs')
5
+ const path = require('node:path')
6
+ const term = require('../util/term')
8
7
 
9
- const { COMMAND_INIT } = require("../init/constants");
8
+ const { pathToFileURL } = require('node:url')
10
9
 
11
- module.exports = {
12
- /**
13
- * Reads ESLint config contents from file
14
- * @param {*} configPath config file path to read from
15
- * @returns {object[] | object} config file contents
16
- */
17
- async readEslintConfigLegacy(configPath) {
18
- let config;
19
- const configFile = path.basename(configPath);
20
- const configString = await read(configPath, "utf8");
21
- switch (configFile) {
22
- case ".eslintrc.js":
23
- case ".eslintrc.cjs":
24
- try {
25
- config = JSONC.parse((configString.replace(/^module\.exports =/, "")));
26
- } catch {
27
- config = {};
28
- }
29
- break;
30
- case ".eslintrc.yaml":
31
- case ".eslintrc.yml":
32
- config = yaml.parse(await read(configPath, "utf8"));
33
- break;
34
- case ".eslintrc.json":
35
- case ".eslintrc":
36
- config = await readJSONC(configPath);
37
- break;
38
- case "package.json":
39
- config = await read(configPath, "json");
40
- if ("eslintConfig" in config) {
41
- config = config["eslintConfig"];
42
- } else {
43
- config = {}
44
- }
45
- break;
46
- default:
47
- break;
48
- }
49
- return config;
50
- },
10
+ const { COMMAND_INIT } = require('../init/constants')
51
11
 
52
- /**
12
+ const installationHint = (logger, configFile, importStatement) => logger.log(
13
+ `${term.warn(
14
+ `\n\nPlease add the following to your '${configFile}':` +
15
+ '\n\n 1. At the top of your file, import the following:')}` +
16
+ `\n\n ${term.bold(importStatement)}` +
17
+ `${term.warn(
18
+ '\n\n 2. In your export, add the following to the front of the array:')}` +
19
+ `\n\n ${term.bold('cdsPlugin.configs.recommended')}`
20
+ )
21
+
22
+ module.exports = {
23
+ /**
53
24
  * Reads ESLint config contents from file
54
- * @param {*} configPath config file path to read from
55
- * @returns config file contents
25
+ * @param {import('fs').PathLike} configPath config file path to read from
26
+ * @returns {Promise<object>} config file contents
56
27
  */
57
28
  async readEslintConfig(configPath) {
58
- let config;
29
+ let config
59
30
  switch (path.basename(configPath)) {
60
- case "eslint.config.mjs":
61
- try { config = await import (configPath) } catch { config = null }
31
+ case 'eslint.config.mjs':
32
+ // pathToFileURL is used to convert the path to a file URL on Windows
33
+ try { config = (await import (pathToFileURL(configPath))).default } catch(e) { config = null }
62
34
  break
63
- case "eslint.config.js":
64
- case "eslint.config.cjs":
35
+ case 'eslint.config.js':
36
+ case 'eslint.config.cjs':
65
37
  try { config = require (configPath) } catch { config = null }
66
38
  }
67
- return config;
39
+ return config
68
40
  },
69
41
 
70
42
  /**
71
43
  * Checks ESLint config file contents for locally installed
72
44
  * plugin with:
73
- * (1) All CDS recommended rules "on"
45
+ * (1) All CDS recommended rules 'on'
74
46
  * (2) Add's custom rule example 'no-entity-moo' if requested
75
- * @param {*} configPath ESLint config file
76
- * @returns {void}
47
+ * @param {object | string} configPath - ESLint config file or path
48
+ * @param {import('console').Console} logger - logger to use
49
+ * @returns {object}
77
50
  */
78
- async sanitizeEslintConfig(configIn, customRuleExample = false, logger = console) {
79
- let configContents;
80
- const isFilePath = typeof configIn === "string";
51
+ async sanitizeEslintConfig(configIn, logger = console) {
52
+ let configContents
53
+ const isFilePath = typeof configIn === 'string'
81
54
  if (isFilePath) {
82
55
  configContents = await this.readEslintConfig(configIn)
83
56
  }
84
57
 
85
- configContents ??= { ...configIn };
86
-
87
- if (customRuleExample) {
88
- const ruleName = "no-entity-moo";
89
- const ruleValue = 2;
90
- if ("rules" in configContents) {
91
- configContents["rules"][ruleName] = ruleValue;
92
- } else {
93
- configContents["rules"] = { [ruleName]: ruleValue };
94
- }
95
- }
58
+ configContents ??= { ...configIn }
96
59
  if (isFilePath) {
97
- await this.writeEslintConfig(configIn, cds.cli?.command === COMMAND_INIT, logger);
98
- }
99
- return configContents;
100
- },
101
-
102
- /**
103
- * Checks ESLint config file contents for locally installed
104
- * plugin with:
105
- * (1) All CDS recommended rules "on"
106
- * (2) Option "root": false to stop further config merging
107
- * (3) Add's custom rule example 'no-entity-moo' if requested
108
- * @param {*} configPath ESLint config file
109
- */
110
- async sanitizeEslintConfigLegacy(configIn, customRuleExample = false, logger = console) {
111
- let configContents = {};
112
- const isFilePath = typeof configIn === "string";
113
- if (isFilePath) {
114
- if (exists(configIn)) {
115
- configContents = (await this.readEslintConfig(configIn)) || {};
116
- }
117
- } else {
118
- configContents = { ...configIn };
119
- }
120
- const configType = "recommended";
121
- const extendsValue = `plugin:@sap/cds/${configType}`;
122
- if ("extends" in configContents) {
123
- if (Array.isArray(configContents["extends"])) {
124
- if (!configContents["extends"].includes(extendsValue)) {
125
- configContents["extends"].push(extendsValue);
126
- }
127
- } else if (configContents["extends"] !== extendsValue) {
128
- configContents["extends"] = [configContents["extends"], extendsValue];
129
- }
130
- } else {
131
- configContents["extends"] = extendsValue;
132
- }
133
- if ("root" in configContents) {
134
- configContents["root"] = false;
135
- }
136
- if (customRuleExample) {
137
- const ruleName = "no-entity-moo";
138
- const ruleValue = 2;
139
- if ("rules" in configContents) {
140
- configContents["rules"][ruleName] = ruleValue;
141
- } else {
142
- configContents["rules"] = { [ruleName]: ruleValue };
143
- }
144
- }
145
- if (isFilePath) {
146
- await this.writeEslintConfigLegacy(configIn, configContents, logger);
147
- }
148
- return configContents;
149
- },
150
-
151
-
152
- /**
153
- * Writes ESLint config contents to file
154
- * @param {*} configContents config file contents
155
- * @param {*} configPath config file path to write to
156
- * @returns {Promise<void>}
157
- */
158
- async writeEslintConfigLegacy(configPath, configContents, logger = console) {
159
- const configType = "recommended-legacy";
160
- const extendsValue = `plugin:@sap/cds/${configType}`;
161
- let contents = {};
162
- let configFile = path.basename(configPath);
163
- let configToAdd = {};
164
- switch (configFile) {
165
- case ".eslintrc.js":
166
- case ".eslintrc.cjs":
167
- try {
168
- configContents = await this.readEslintConfigLegacy(configPath);
169
- } catch (err) {
170
- configContents = {};
171
- }
172
- if (configContents && configContents["extends"]) {
173
- if (
174
- !configContents["extends"] === extendsValue ||
175
- !configContents["extends"].includes(extendsValue)
176
- ) {
177
- configToAdd["extends"] = extendsValue;
178
- }
179
- } else {
180
- configToAdd["extends"] = extendsValue;
181
- }
182
- if (configToAdd["extends"]) {
183
- logger.log(
184
- `${term.warn(
185
- `\n\nPlease add the following to your "${configFile}":\n\nmodule.exports = ${JSON.stringify(configToAdd, null, 2)}`
186
- )}\n`
187
- );
188
- }
189
- break;
190
- case ".eslintrc.yaml":
191
- case ".eslintrc.yml":
192
- await write(configPath, yaml.stringify(configContents));
193
- break;
194
- case ".eslintrc.json":
195
- case ".eslintrc":
196
- await write(configPath, configContents, { spaces: 2 });
197
- break;
198
- case "package.json":
199
- if (exists(configPath)) {
200
- contents = await read(configPath, "json");
201
- } else {
202
- contents = {};
203
- }
204
- if (!("eslintConfig" in configContents)) {
205
- contents["eslintConfig"] = configContents;
206
- } else {
207
- contents["eslintConfig"] = [...configContents, ...contents["eslintConfig"]];
208
- }
209
- await write(configPath, contents, { spaces: 2 });
210
- break;
211
- default:
212
- break;
60
+ await this.writeEslintConfig(configIn, cds.cli?.command === COMMAND_INIT, logger)
213
61
  }
62
+ return configContents
214
63
  },
215
64
 
216
65
  /**
217
66
  * Suggest ESLint config contents to file
218
67
  * @param {*} configContents config file contents
219
- * @param {*} configPath config file path to write to
68
+ * @param {import('node:fs').PathLike} configPath config file path to write to
220
69
  * @returns {Promise<void>}
221
70
  */
222
71
  async writeEslintConfig(configPath, force = false, logger = console) {
223
- let configFile = path.basename(configPath);
72
+ let configFile = path.basename(configPath)
224
73
  switch (configFile) {
225
- case "eslint.config.js":
226
- case "eslint.config.cjs":
74
+ case 'eslint.config.js':
75
+ case 'eslint.config.cjs':
227
76
  if (!force && exists(configPath)) {
228
- logger.log(
229
- `${term.warn(
230
- `\n\nPlease add the following to your "${configFile}":` +
231
- '\n\n 1. At the top of your file, import the following:')}` +
232
- `\n\n ${term.bold('const cds = require(\'@sap/eslint-plugin-cds\')')}` +
233
- `${term.warn(
234
- '\n\n 2. In your export, add the following to the top of the array:')}` +
235
- `\n\n ${term.bold('cds.configs.recommended')}`
236
- );
77
+ installationHint(logger, configFile, 'const cdsPlugin = require(\'@sap/eslint-plugin-cds\')')
237
78
  } else {
238
79
  await write(configPath, `
239
80
  const cds = require('@sap/eslint-plugin-cds')
240
81
 
241
- module.exports = [
242
- cds.configs.recommended,
243
- {
244
- plugins: {
245
- '@sap/cds': cds
246
- },
247
- files: [
248
- ...cds.configs.recommended.files
249
- ],
250
- rules: {
251
- ...cds.configs.recommended.rules
252
- }
253
- }
254
- ]
82
+ module.exports = [...cds.recommended, cdsPlugin.configs.recommended]
255
83
  `)
256
84
  }
257
- break;
258
- case "eslint.config.mjs":
85
+ logger.log(term.warn('\nMake sure to also run npm i to install the newly added dependencies.'))
86
+ break
87
+
88
+ case 'eslint.config.mjs':
259
89
  if (!force && exists(configPath)) {
260
- logger.log(
261
- `${term.warn(
262
- `\n\nPlease add the following to your "${configFile}":` +
263
- '\n\n 1. At the top of your file, import the following:')}` +
264
- `\n\n ${term.bold('import cdsPlugin from \'@sap/eslint-plugin-cds\'')}` +
265
- `${term.warn(
266
- '\n\n 2. In your export, add the following to the front of the array:')}` +
267
- `\n\n ${term.bold('cdsPlugin.configs.recommended')}`
268
- );
90
+ installationHint(logger, configFile, 'import cdsPlugin from \'@sap/eslint-plugin-cds\'')
269
91
  } else {
270
92
  await write(configPath, `
271
93
  import cds from '@sap/cds/eslint.config.mjs'
@@ -274,9 +96,8 @@ import cdsPlugin from '@sap/eslint-plugin-cds'
274
96
  export default [...cds.recommended, cdsPlugin.configs.recommended]
275
97
  `)
276
98
  }
277
- break;
278
- default:
279
- break;
99
+ logger.log(term.warn('\nMake sure to also run npm i to install the newly added dependencies.'))
100
+ break
280
101
  }
281
102
  },
282
103
 
@@ -286,15 +107,15 @@ export default [...cds.recommended, cdsPlugin.configs.recommended]
286
107
  * @returns settings file contents
287
108
  */
288
109
  async readVscodeSettings(settingsPath) {
289
- let settings;
110
+ let settings
290
111
  if (exists(settingsPath)) {
291
112
  try {
292
- settings = await readJSONC(settingsPath);
293
- } catch (err) {
294
- settings = {};
113
+ settings = await readJSONC(settingsPath)
114
+ } catch {
115
+ settings = {}
295
116
  }
296
117
  }
297
- return settings;
118
+ return settings
298
119
  },
299
120
 
300
121
  /**
@@ -304,71 +125,38 @@ export default [...cds.recommended, cdsPlugin.configs.recommended]
304
125
  * @returns merged array (without duplicates)
305
126
  */
306
127
  mergeArrays(array, arrayToMerge) {
307
- let arrayMerged = array.concat(arrayToMerge);
308
- if (typeof array === "string") {
309
- array = [array];
128
+ let arrayMerged = array.concat(arrayToMerge)
129
+ if (typeof array === 'string') {
130
+ array = [array]
310
131
  }
311
- if (typeof arrayToMerge === "string") {
312
- arrayToMerge = [arrayToMerge];
132
+ if (typeof arrayToMerge === 'string') {
133
+ arrayToMerge = [arrayToMerge]
313
134
  }
314
- arrayMerged = [...new Set([...array, ...arrayToMerge])];
315
- return arrayMerged;
135
+ arrayMerged = [...new Set([...array, ...arrayToMerge])]
136
+ return arrayMerged
316
137
  },
317
138
 
318
139
  /**
319
140
  * Add VS Code ESLint extension settings required for CDS linting:
320
141
  * (1) Extension file types: [cds, csn]
321
- * (2) "Custom" case adds rulePaths and removes configFile
322
- * (3) "Global" case adds configFile and removes rulePaths
142
+ * (2) 'Custom' case adds rulePaths and removes configFile
143
+ * (3) 'Global' case adds configFile and removes rulePaths
323
144
  * @param {*} settingsPath VS Code settings file
324
145
  */
325
- async sanitizeVscodeSettings(settingsPath, lintType, lintFileTypes, customRuleExample = false) {
326
- let settings = (await this.readVscodeSettings(settingsPath)) || {};
327
- const rulePaths = [path.join(".eslint/rules")];
146
+ async sanitizeVscodeSettings(settingsPath, lintFileTypes, customRuleExample = false) {
147
+ const settings = (await this.readVscodeSettings(settingsPath)) ?? {}
148
+ const rulePaths = [path.join('.eslint/rules')]
328
149
 
329
- if (settings["eslint.validate"]) {
330
- settings["eslint.validate"] = this.mergeArrays(settings["eslint.validate"], lintFileTypes);
331
- } else {
332
- settings["eslint.validate"] = lintFileTypes;
333
- }
150
+ settings['eslint.validate'] = settings['eslint.validate']
151
+ ? this.mergeArrays(settings['eslint.validate'], lintFileTypes)
152
+ : lintFileTypes
334
153
 
335
- if (lintType === "local") {
336
- if (settings["eslint.options"]) {
337
- if (customRuleExample) {
338
- settings["eslint.options"]["rulePaths"] = rulePaths;
339
- }
340
- } else {
341
- if (customRuleExample) {
342
- settings["eslint.options"] = {
343
- rulePaths: rulePaths,
344
- };
345
- }
346
- }
154
+ if (settings['eslint.options'] && customRuleExample) {
155
+ settings['eslint.options'].rulePaths = rulePaths
156
+ } else if (customRuleExample) {
157
+ settings['eslint.options'] = { rulePaths: rulePaths }
347
158
  }
348
159
 
349
- await write(settingsPath, settings, { spaces: 2 });
350
- },
351
-
352
- /**
353
- * Joins or creates prescribed options with that of user
354
- * - Value for 'config' key will be overwritten if assigned by `cds lint`
355
- * @param {*} propKey option key property
356
- * @param {*} propsToAdd option values to add for key property
357
- * @returns {void}
358
- */
359
- mergeWithUserOpts(userOpts, propKey = "", propsToAdd = "") {
360
- if (propsToAdd) {
361
- if (Object.keys(userOpts).includes(propKey)) {
362
- if (!["config", "format"].includes(propKey)) {
363
- propsToAdd = this.mergeArrays(userOpts[propKey].split(","), propsToAdd.split(",")).join(
364
- ","
365
- );
366
- }
367
- }
368
- userOpts[propKey] = propsToAdd;
369
- } else {
370
- userOpts[propKey] = true;
371
- }
372
- return userOpts;
160
+ await write(settingsPath, settings, { spaces: 2 })
373
161
  },
374
- };
162
+ }
package/lib/util/fs.js CHANGED
@@ -1,4 +1,5 @@
1
- const { read, write, yaml: YAML } = require('../cds').utils
1
+ const YAML = require('yaml')
2
+ const { read, write } = require('../cds').utils
2
3
  const JSONC = require('./jsonc');
3
4
 
4
5
  // REVISIT: Consider merging with template util
package/lib/util/git.js CHANGED
@@ -5,7 +5,7 @@ const util = require('util');
5
5
  const os = require('os');
6
6
 
7
7
  const cds = require('../cds');
8
- const DEBUG = cds.debug('cli');
8
+ const DEBUG = /\b(y|all|cli)\b/.test (process.env.DEBUG) ? ((..._) => console.debug ('[cli] -', ..._)) : undefined
9
9
 
10
10
  const GIT_IGNORE_FILE = '.gitignore';
11
11