@sap/cds-dk 4.6.3 → 4.7.3

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.
@@ -22,11 +22,11 @@ module.exports = class HanaTemplate extends TemplateBase {
22
22
 
23
23
  const env = await this.getEnv();
24
24
 
25
- const hdiConfigPath = path.join(this.projectPath, env.folders.db, 'src/.hdiconfig');
26
- if (await this.fsUtil.pathExists(hdiConfigPath)) {
27
- const configFilePath = path.join(env.folders.db, 'src/.hdiconfig');
28
- throw new Error(`Database config file ${configFilePath} already exists. Use --force to overwrite.`);
29
- }
25
+ await Promise.all(['src/.hdiconfig', 'undeploy.json'].map(async(filePath) => {
26
+ if (await this.fsUtil.pathExists(path.join(this.projectPath, env.folders.db, filePath))) {
27
+ throw new Error(`File ${path.join(env.folders.db, filePath)} already exists. Use --force to overwrite.`);
28
+ }
29
+ }))
30
30
 
31
31
  return true;
32
32
  }
@@ -9,10 +9,15 @@ const readline = require("readline");
9
9
 
10
10
  const { OPTION_LINT_DEV, OPTION_LINT_GLOBAL } = require("../../constants");
11
11
  const { mkdirp, fs } = require("@sap/cds/lib/utils");
12
- const { getConfigPath } = require("@sap/eslint-plugin-cds/lib/api");
12
+ const { getConfigPath, getFileExtensions } = require("@sap/eslint-plugin-cds/lib/api");
13
13
  const generators = require("../../../lint/generators");
14
14
 
15
15
  const IS_WIN = os.platform() === "win32";
16
+ const ALLOWED_FILE_EXTENSIONS = getFileExtensions();
17
+ const VSCODE_FILE_ASSOCIATIONS = {
18
+ "csv": [ "csv", "csv (semicolon)", "tsv", "tab" ]
19
+ }
20
+
16
21
  module.exports = class LintTemplate extends TemplateBase {
17
22
  constructor(projectPath, generator) {
18
23
  super(projectPath, generator, __dirname);
@@ -68,10 +73,21 @@ module.exports = class LintTemplate extends TemplateBase {
68
73
  }
69
74
 
70
75
  // Generate VS Code extension settings
76
+ const extensions = ALLOWED_FILE_EXTENSIONS.map((ext) => {
77
+ return path.extname(ext).replace('.', '');
78
+ })
79
+ extensions.forEach((ext) => {
80
+ if (ext in VSCODE_FILE_ASSOCIATIONS) {
81
+ VSCODE_FILE_ASSOCIATIONS[ext].forEach((assoc) => {
82
+ extensions.push(assoc)
83
+ })
84
+ }
85
+ });
71
86
  await io.sanitizeVscodeSettings(
72
87
  this.projectPath,
73
88
  path.join(this.projectPath, ".vscode/settings.json"),
74
89
  this.lintType,
90
+ extensions,
75
91
  this.customRuleExample
76
92
  );
77
93
  }
@@ -13,7 +13,12 @@ build-parameters:
13
13
  before-all:
14
14
  - builder: custom
15
15
  commands:
16
+ {{#cap.isNodejs}}
17
+ - npm ci
18
+ {{/cap.isNodejs}}
19
+ {{#cap.isJava}}
16
20
  - npm install --production
21
+ {{/cap.isJava}}
17
22
  - npx -p @sap/cds-dk cds build --production
18
23
 
19
24
  {{! This template creates one or two deployable modules:
@@ -30,6 +35,8 @@ modules:
30
35
  {{#cap.isNodejs}}
31
36
  parameters:
32
37
  buildpack: nodejs_buildpack
38
+ build-parameters:
39
+ builder: npm-ci
33
40
  {{/cap.isNodejs}}
34
41
  {{#cap.isJava}}
35
42
  parameters:
@@ -207,11 +214,11 @@ resources:
207
214
  type: org.cloudfoundry.managed-service
208
215
  requires:
209
216
  - name: {{cap.appName}}-uaa-mt
210
- - name: mtx-api
211
- properties:
212
- prop: ~{mtx-url}
213
- parameters:
214
- param: ~{mtx-url}
217
+ - name: mtx-api
218
+ properties:
219
+ prop: ~{mtx-url}
220
+ parameters:
221
+ param: ~{mtx-url}
215
222
  parameters:
216
223
  service: saas-registry
217
224
  service-plan: application
@@ -18,7 +18,7 @@ module.exports = class FsUtil {
18
18
  await fse.outputFile(filepath, content, UTF_8);
19
19
  }
20
20
 
21
- async writeJSON(filepath, object, options = { spaces: 4 }, skipFileLog = false) {
21
+ async writeJSON(filepath, object, options = { spaces: 2 }, skipFileLog = false) {
22
22
  if (!skipFileLog) {
23
23
  this._addTouchedFile(filepath);
24
24
  }
@@ -31,7 +31,9 @@ class MvnArchetypeUtil {
31
31
 
32
32
  params.set('-B');
33
33
 
34
- defaultLogger.isDebug && params.set('-X');
34
+ if (defaultLogger.isDebug) {
35
+ params.set('-X'); params.set('-e');
36
+ }
35
37
 
36
38
  return Array.from(params, (e) => {
37
39
  let result = e[0];
@@ -23,7 +23,6 @@ class Linter {
23
23
  this.eslintCmdOpts = {};
24
24
  this.eslintCmdOptsIndex = 0;
25
25
  this.eslintCmdFileExpr = "";
26
- this.formatter = false;
27
26
  this.isFile = false;
28
27
  this.help = "";
29
28
  this.debug = "";
@@ -141,7 +140,7 @@ class Linter {
141
140
 
142
141
  _addExtensions() {
143
142
  // Add CDS file extensions to lint
144
- const extensions = ALLOWED_FILE_EXTENSIONS.map((ext) => ext.replace('*.', '.'));
143
+ const extensions = ALLOWED_FILE_EXTENSIONS.map((ext) => path.extname(ext));
145
144
  this.eslintCmdOpts = io.mergeWithUserOpts(
146
145
  this.eslintCmdOpts,
147
146
  "ext",
package/lib/lint/io.js CHANGED
@@ -22,7 +22,7 @@ module.exports = {
22
22
  case ".eslintrc.js":
23
23
  case ".eslintrc.cjs":
24
24
  try {
25
- config = JSON.parse(configString.replace(/^module\.exports =/, ""));
25
+ config = JSONC.parse((configString.replace(/^module\.exports =/, "")));
26
26
  } catch (err) {
27
27
  config = {};
28
28
  }
@@ -33,7 +33,7 @@ module.exports = {
33
33
  break;
34
34
  case ".eslintrc.json":
35
35
  case ".eslintrc":
36
- config = JSON.parse(await fsp.readFile(configPath, "utf8"));
36
+ config = await fsUtil.readJSONC(configPath);
37
37
  break;
38
38
  case "package.json":
39
39
  config = JSON.parse(await fsp.readFile(configPath, "utf8"));
@@ -201,18 +201,9 @@ module.exports = {
201
201
  * (3) "Global" case adds configFile and removes rulePaths
202
202
  * @param {*} settingsPath VS Code settings file
203
203
  */
204
- async sanitizeVscodeSettings(projectPath, settingsPath, lintType, customRuleExample = false) {
204
+ async sanitizeVscodeSettings(projectPath, settingsPath, lintType, lintFileTypes, customRuleExample = false) {
205
205
  let settings = (await this.readVscodeSettings(settingsPath)) || {};
206
- const lintFileTypes = ["cds", "csn"];
207
206
  const rulePaths = [path.join(".eslint/rules")];
208
- const configFile = path.join(__dirname, ".eslintrc.js");
209
-
210
- function _addArrayOrString(array) {
211
- if (array.length === 1) {
212
- return array[0];
213
- }
214
- return array;
215
- }
216
207
 
217
208
  if (settings["eslint.validate"]) {
218
209
  settings["eslint.validate"] = this.mergeArrays(settings["eslint.validate"], lintFileTypes);
@@ -1,3 +1,5 @@
1
+ const DEBUG = /\bwatch\b/.test(process.env.DEBUG) && console.debug
2
+
1
3
  module.exports = ({ cwd, script, ext, ignore=RegExp(), env={}, delay=200, options={} })=>{
2
4
 
3
5
  let child
@@ -5,19 +7,23 @@ module.exports = ({ cwd, script, ext, ignore=RegExp(), env={}, delay=200, option
5
7
  // Phoning home...
6
8
  const EventEmitter = require('events')
7
9
  const emitter = new EventEmitter
8
- process.on('exit', () => { gracefullyKill (child); emitter.emit('quit') })
10
+ process.on('exit', () => { _kill (child); emitter.emit('quit') })
9
11
 
10
12
  // Re-starting child process...
11
13
  const { fork } = require('child_process')
12
- const restart = (evt, name)=>{
13
- gracefullyKill (child, () => {
14
+ const restart = _coalesceEvents(delay, (events) => {
15
+ DEBUG && DEBUG('>> Events:', events)
16
+ _kill (child, () => {
14
17
  const execArgv = [...process.execArgv]
15
- if (evt && evt.startsWith('--')) execArgv.push(evt)
16
- if (name && name.startsWith('--')) execArgv.push(name)
18
+ events.forEach(evt => {
19
+ if (evt.type && evt.type.startsWith('--')) execArgv.push(evt.type)
20
+ if (evt.name && evt.name.startsWith('--')) execArgv.push(evt.name)
21
+ })
17
22
  if (options.debug) execArgv.push('--inspect')
18
23
  if (options['debug-brk']) execArgv.push('--inspect-brk')
19
- const files = evt === "update" ? [ name ] : undefined
20
- emitter.emit ('restart', files)
24
+
25
+ const updated = events.filter(evt => evt.type && evt.type === 'update').map(evt => evt.name)
26
+ emitter.emit ('restart', updated)
21
27
  child = fork (script, { cwd, env, stdio:'inherit', execArgv }, (err)=>{
22
28
  if (err) console.error (err)
23
29
  })
@@ -26,14 +32,16 @@ module.exports = ({ cwd, script, ext, ignore=RegExp(), env={}, delay=200, option
26
32
  emitter.emit('message', msg)
27
33
  })
28
34
  })
29
- }
35
+
36
+ })
37
+
30
38
  restart()
31
39
 
32
40
  // Watching for touched files...
33
41
  const watch = require('node-watch')
34
42
  const include = RegExp(`\\.(${ext.replace(/,/g,'|')})$`)
35
43
  const filter = f => !ignore.test(f) && include.test(f)
36
- watch (process.cwd(),{ recursive:true, filter, delay }, restart)
44
+ watch (process.cwd(),{ recursive:true, filter, delay:0 }, restart)
37
45
 
38
46
  // Live commands...
39
47
  const readline = require('readline')
@@ -44,12 +52,12 @@ module.exports = ({ cwd, script, ext, ignore=RegExp(), env={}, delay=200, option
44
52
  else if (input === 'break' || input === 'brk') restart('--inspect-brk')
45
53
  else if (input === 'debug-brk') restart('--inspect-brk')
46
54
  else if (input === 'ps') ps(child,env)
47
- else if (input === 'bye' || input.match(/^n$/i)) { gracefullyKill (child, () => process.exit()) }
55
+ else if (input === 'bye' || input.match(/^n$/i)) { _kill (child, () => process.exit()) }
48
56
  else console.log ('?\n')
49
57
  })
50
58
 
51
59
  emitter.restart = restart
52
- emitter.stop = () => { gracefullyKill(child, () => false); child = undefined; }
60
+ emitter.stop = () => { _kill(child, () => false); child = undefined; }
53
61
  emitter.setEnv = (name, value) => {
54
62
  if (typeof value === "undefined") {
55
63
  delete env[name]
@@ -67,14 +75,32 @@ const ps = (child,env) => console.log (`\x1b[32m
67
75
  \x1b[0m`
68
76
  )
69
77
 
70
- // On Windows, kill() abruptly kills the child process (https://nodejs.org/api/child_process.html#subprocesskillsignal)
71
- // Send a custom message an wait a bit to give cleanup code a chance to execute.
72
- const isWindows = (process.platform === 'win32')
73
- const waitTime = parseInt(process.env.CDS_WATCH_KILL_DELAY) || (isWindows ? 500 : 0)
74
- function gracefullyKill (proc, fn=()=>{}) {
75
- if (proc) {
76
- proc.send({ exit: true }, () => { /* ignore */ })
77
- setTimeout(()=> { proc.kill(); fn()}, waitTime)
78
+ // reduces mutiple node-watch events in a time frame into a bulk
79
+ function _coalesceEvents(delay, fn) {
80
+ let timer, cache = []
81
+ function handle() {
82
+ fn(cache)
83
+ timer = null
84
+ cache = []
85
+ }
86
+ return function(type, name) { // node-watch callback signature
87
+ cache.push({type, name})
88
+ if (!timer) {
89
+ timer = setTimeout(handle, delay);
90
+ }
91
+ }
92
+ }
93
+
94
+ function _kill (proc, fn=()=>{}) {
95
+ if (!proc) return fn()
96
+
97
+ // On Windows, child_process.kill() abruptly kills the process (https://nodejs.org/api/child_process.html#subprocesskillsignal)
98
+ // Server has cleanup code to run, so send a custom message and give it a bit time.
99
+ if (process.platform === 'win32') {
100
+ proc.send({ exit: true }, () => {})
101
+ const waitTime = parseInt(process.env.CDS_WATCH_KILL_DELAY) || 500
102
+ setTimeout(()=> { proc.kill(); fn() }, waitTime)
103
+ } else {
104
+ proc.kill(); fn()
78
105
  }
79
- else fn()
80
106
  }