@sap/cds-dk 6.2.2 → 6.3.0

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 (72) hide show
  1. package/CHANGELOG.md +38 -0
  2. package/bin/bind.js +4 -4
  3. package/bin/deploy/to-h2.js +4 -0
  4. package/bin/deploy/to-sqlite.js +6 -4
  5. package/bin/help.js +1 -1
  6. package/bin/login.js +1 -0
  7. package/bin/mock.js +2 -2
  8. package/bin/push.js +29 -7
  9. package/lib/bind/userCdsrcJsonStorageProvider.js +4 -4
  10. package/lib/cds.js +6 -3
  11. package/lib/client/activate.js +1 -1
  12. package/lib/client/base_command.js +10 -10
  13. package/lib/client/helper/dependency_helper.js +10 -1
  14. package/lib/client/helper/logging.js +6 -2
  15. package/lib/client/pull.js +6 -6
  16. package/lib/client/push.js +33 -14
  17. package/lib/client/settings_manager.js +52 -21
  18. package/lib/compile/openapi/csdl2openapi.js +1 -1
  19. package/lib/compile/to-xsuaa.js +1 -1
  20. package/lib/import/odata/v2parser.js +37 -1
  21. package/lib/import/odata/v4parser.js +101 -23
  22. package/lib/init/constants.js +1 -1
  23. package/lib/init/index.js +23 -45
  24. package/lib/init/template/approuter/index.js +44 -48
  25. package/lib/init/template/auditlog/index.js +14 -10
  26. package/lib/init/template/cf-manifest/index.js +9 -11
  27. package/lib/init/template/connectivity/index.js +10 -10
  28. package/lib/init/template/data/index.js +20 -19
  29. package/lib/init/template/destinations/index.js +14 -9
  30. package/lib/init/template/enterprise-messaging/index.js +14 -9
  31. package/lib/init/template/extensibility/index.js +14 -9
  32. package/lib/init/template/hana/index.js +51 -57
  33. package/lib/init/template/helm/index.js +27 -59
  34. package/lib/init/template/helm/subchart/templates/_helpers.tpl +38 -0
  35. package/lib/init/template/helm/subchart/templates/deployment.yaml +12 -12
  36. package/lib/init/template/helm/subchart/values.md +565 -194
  37. package/lib/init/template/helm/subchart/values.schema.json +163 -8
  38. package/lib/init/template/helm/subchart/values.yaml +17 -1
  39. package/lib/init/template/html5-repo/index.js +15 -11
  40. package/lib/init/template/java/index.js +15 -11
  41. package/lib/init/template/kibana-logging/index.js +30 -31
  42. package/lib/init/template/lint/index.js +17 -18
  43. package/lib/init/template/mta/index.js +18 -40
  44. package/lib/init/template/mtx/index.js +2 -3
  45. package/lib/init/template/multitenancy/index.js +27 -20
  46. package/lib/init/template/nodejs/index.js +18 -20
  47. package/lib/init/template/notebook/index.js +5 -434
  48. package/lib/init/template/pipeline/index.js +10 -10
  49. package/lib/init/template/samples/index.js +7 -16
  50. package/lib/init/template/templateBase.js +17 -18
  51. package/lib/init/template/toggles/files/cdsrc.json +5 -0
  52. package/lib/init/template/toggles/files/cdsrc.json.hbs +7 -0
  53. package/lib/init/template/toggles/index.js +12 -6
  54. package/lib/init/template/xsuaa/index.js +44 -41
  55. package/lib/init/types.d.ts +0 -59
  56. package/lib/init/util/commandUtil.js +6 -7
  57. package/lib/init/util/fsUtil.js +23 -109
  58. package/lib/init/util/merge.js +319 -0
  59. package/lib/init/util/mvnArchetypeUtil.js +6 -5
  60. package/lib/init/util/projectReader.js +125 -300
  61. package/lib/init/util/spinner.js +10 -8
  62. package/lib/init/util/templateUtil.js +25 -368
  63. package/lib/lint/Linter.js +2 -3
  64. package/lib/lint/checks.js +0 -1
  65. package/lib/lint/io.js +18 -34
  66. package/npm-shrinkwrap.json +115 -261
  67. package/package.json +3 -3
  68. package/lib/init/template/notebook/cap_magic.py +0 -118
  69. package/lib/init/template/notebook/files/{{{name}}}.ipynb.hbs +0 -90
  70. package/lib/init/template/notebook/files/{{{name}}}.json +0 -102
  71. package/lib/init/template/notebook/notebook.js +0 -394
  72. package/lib/init/util/logger.js +0 -42
@@ -1,24 +1,15 @@
1
1
  const path = require('path');
2
-
3
- const TemplateBase = require('../templateBase');
4
-
2
+ const { copyFiles } = require('../../util/templateUtil')
5
3
  const commandUtil = require('../../util/commandUtil');
6
4
  const mvnArchetypes = require('../../util/mvnArchetypeUtil');
7
5
  const term = require('../../../util/term');
8
-
9
6
  const { PROJECT_TYPE, OPTION_JAVA, URLS } = require('../../constants');
10
7
 
11
-
12
-
13
- module.exports = class SamplesTemplate extends TemplateBase {
8
+ module.exports = class SamplesTemplate extends require('../templateBase') {
14
9
  constructor(projectPath, generator) {
15
10
  super(projectPath, generator, __dirname);
16
11
  }
17
12
 
18
- async checkEnabled() {
19
- return true;
20
- }
21
-
22
13
  async run() {
23
14
  switch (await this.getProjectType()) {
24
15
  case PROJECT_TYPE.java:
@@ -35,19 +26,19 @@ module.exports = class SamplesTemplate extends TemplateBase {
35
26
 
36
27
  async _addJavaSamples() {
37
28
  // only execute if not add via cds init --add java, otherwise samples would be added twice
38
- // do not check in checkEnabled since log output "> adding samples" wouldn't appear
29
+ // do not check in canRun since log output "> adding samples" wouldn't appear
39
30
  if (!this.options.add.has(OPTION_JAVA)) {
40
31
  // keep sequence since plugin needs samples to generate test classes
41
32
  const mvnAddSamplesArgs = mvnArchetypes.getAddSamplesCmdArgs(this.options);
42
33
  try {
43
34
  await commandUtil.spawnCommand('mvn', mvnAddSamplesArgs, {
44
35
  cwd: this.projectPath
45
- }, this.logger);
36
+ });
46
37
 
47
38
  const mvnAddTestsArgs = mvnArchetypes.getAddTestsCmdArgs(this.options);
48
39
  await commandUtil.spawnCommand('mvn', mvnAddTestsArgs, {
49
40
  cwd: this.projectPath
50
- }, this.logger);
41
+ });
51
42
  } catch (err) {
52
43
  if (err.code === 'ENOENT' && err.path === 'mvn') {
53
44
  throw new Error(`Maven executable 'mvn' not found, follow ${term.info(URLS.MAVEN_INSTALL_HELP)} and install Maven on your machine.`);
@@ -60,10 +51,10 @@ module.exports = class SamplesTemplate extends TemplateBase {
60
51
  async _addNodejsSamples() {
61
52
  const folders = (await this.getEnv()).folders;
62
53
  const dbFolder = path.join(this.projectPath, folders.db);
63
- await this.templateUtil.copyFiles('nodejs/db', dbFolder, {}, this.options.force);
54
+ await copyFiles(path.join(__dirname, 'files', 'nodejs', 'db'), dbFolder, {}, this.options.force);
64
55
 
65
56
  const srvFolder = path.join(this.projectPath, folders.srv);
66
- await this.templateUtil.copyFiles('nodejs/srv', srvFolder, {
57
+ await copyFiles(path.join(__dirname, 'files', 'nodejs', 'srv'), srvFolder, {
67
58
  dbFolder: folders.db.replace(/[\\/]+$/, '')
68
59
  }, this.options.force);
69
60
  }
@@ -4,29 +4,25 @@ const path = require('path');
4
4
  const TemplateUtil = require('../util/templateUtil');
5
5
 
6
6
  const { PROJECT_TYPE } = require('../constants');
7
-
7
+ const { exists } = require('../../cds').utils;
8
8
 
9
9
  module.exports = class TemplateBase {
10
10
  /**
11
11
  * @constructor
12
12
  */
13
- constructor(projectPath, generator, dirName, dontAnnounce) {
13
+ constructor(projectPath, generator, dirName) {
14
14
  if (generator.options && generator.options.for && typeof generator.options.for !== 'string') {
15
15
  throw new Error('The --for argument must not be empty.')
16
16
  }
17
17
  this.projectPath = path.resolve(projectPath);
18
18
  this.options = generator.options || {};
19
19
  this.projectPath = path.resolve(projectPath);
20
- this.fsUtil = generator.fsUtil;
21
- this.logger = generator.logger;
22
20
  this.generator = generator;
23
21
 
24
22
  this.cwd = this.options.cwd || process.cwd();
25
23
  this.name = (dirName ? path.basename(dirName) : this.constructor.name.replace(/template/i, '').toLowerCase());
26
- this.dontAnnounce = dontAnnounce;
27
24
 
28
25
  this.projectName = path.basename(this.projectPath);
29
- this.templateUtil = new TemplateUtil(path.join(dirName, 'files'), this.fsUtil);
30
26
  }
31
27
 
32
28
  /**
@@ -42,24 +38,27 @@ module.exports = class TemplateBase {
42
38
  * @returns true, if template should handle this request, false otherwise
43
39
  * @throws Error, if request is invalid, e.g. a file exists already
44
40
  */
45
- async checkEnabled() {
41
+ async canRun() {
42
+ return true;
43
+ }
44
+
45
+ // eslint-disable-next-line no-unused-vars
46
+ static hasFacet(env, projectPath, options) {
46
47
  return true;
47
48
  }
48
49
 
49
50
  /**
50
51
  * calls cds env and caches result
51
- * @param {boolean} force, ignore cached value
52
52
  * @returns {object} the current cds env
53
53
  */
54
- async getEnv() {
55
- let projectPath;
56
- if (await this.fsUtil.pathExists(this.projectPath)) {
57
- projectPath = this.projectPath;
58
- } else {
59
- projectPath = this.cwd;
54
+ async getEnv(profile = 'production') {
55
+ const cdsEnvVar = process.env.CDS_ENV
56
+ process.env.CDS_ENV = profile
57
+ try {
58
+ return cds.env.for('cds', exists(this.projectPath) ? this.projectPath : this.cwd);
59
+ } finally {
60
+ cdsEnvVar ? process.env.CDS_ENV = cdsEnvVar : delete process.env.CDS_ENV
60
61
  }
61
-
62
- return cds.env.for('cds', projectPath);
63
62
  }
64
63
 
65
64
  /**
@@ -98,11 +97,11 @@ module.exports = class TemplateBase {
98
97
  * @returns PROJECT_TYPE for current project
99
98
  */
100
99
  async getProjectType() {
101
- if (await this.fsUtil.pathExists(path.join(this.projectPath, 'pom.xml'))) {
100
+ if (exists(path.join(this.projectPath, 'pom.xml'))) {
102
101
  return PROJECT_TYPE.java;
103
102
  }
104
103
 
105
- if (await this.fsUtil.pathExists(path.join(this.projectPath, 'package.json'))) {
104
+ if (exists(path.join(this.projectPath, 'package.json'))) {
106
105
  return PROJECT_TYPE.nodejs;
107
106
  }
108
107
 
@@ -0,0 +1,5 @@
1
+ {
2
+ "requires": {
3
+ "toggles": true
4
+ }
5
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ "requires": {
3
+ "[{{cap.for}}]": {
4
+ "toggles": true
5
+ }
6
+ }
7
+ }
@@ -1,11 +1,15 @@
1
1
  const cds = require('../../../cds'), { path } = cds.utils
2
- const TemplateBase = require('../templateBase')
3
2
  const ProjectReader = require('../../util/projectReader')
3
+ const { mergeJSON, sortDependencies } = require('../../util/merge')
4
4
 
5
- module.exports = class TogglesTemplate extends TemplateBase {
5
+ module.exports = class TogglesTemplate extends require('../templateBase') {
6
6
  constructor(projectPath, generator) {
7
7
  super(projectPath, generator, __dirname)
8
- this.projectReader = new ProjectReader(this)
8
+ this.projectReader = new ProjectReader(projectPath)
9
+ }
10
+
11
+ static hasFacet(env) {
12
+ return !!env.requires?.toggles
9
13
  }
10
14
 
11
15
  async run() {
@@ -14,10 +18,12 @@ module.exports = class TogglesTemplate extends TemplateBase {
14
18
  if (isNodejs) {
15
19
  const packageJSONPath = path.join(this.projectPath, 'package.json')
16
20
  const cdsTemplateFile = forProfile ? 'cds.package.json.hbs' : 'cds.package.json'
17
- await this.templateUtil.mergeJSON(packageJSONPath, path.join(__dirname, 'files', cdsTemplateFile), projectDescriptor)
18
- await this.templateUtil.sortDependencies(packageJSONPath)
21
+ await mergeJSON(packageJSONPath, path.join(__dirname, 'files', cdsTemplateFile), projectDescriptor)
22
+ await sortDependencies(packageJSONPath)
19
23
  } else if (isJava) {
20
- // TODO: implement
24
+ const cdsrcPath = path.join(this.projectPath, '.cdsrc.json')
25
+ const cdsTemplateFile = path.join(__dirname, 'files', forProfile ? 'cdsrc.json.hbs' : 'cdsrc.json')
26
+ await mergeJSON(cdsrcPath, cdsTemplateFile, projectDescriptor)
21
27
  }
22
28
  await this.runDependentMerging()
23
29
  }
@@ -1,19 +1,48 @@
1
1
  const path = require('path')
2
- const cds = require('../../../cds'), { fs } = cds.utils
3
- const TemplateBase = require('../templateBase')
2
+ const cds = require('../../../cds')
3
+ const { copy } = cds.utils
4
4
  const ProjectReader = require('../../util/projectReader')
5
+ const { mergeJSON, mergeYAML } = require('../../util/merge')
5
6
  const { srvNode, srvJava, xsuaa, mtxSidecar } = require('../_merging/registry-mta')
6
7
  const { PROJECT_TYPE } = require('../../constants')
7
8
 
8
- module.exports = class XsuaaTemplate extends TemplateBase {
9
+ module.exports = class XsuaaTemplate extends require('../templateBase') {
9
10
  constructor(projectPath, generator) {
10
11
  super(projectPath, generator, __dirname)
11
- this.projectReader = new ProjectReader(this)
12
+ this.projectReader = new ProjectReader(projectPath)
13
+ }
14
+
15
+ static hasFacet(env) {
16
+ return env.requires?.auth?.kind === 'xsuaa'
17
+ }
18
+
19
+ async run() {
20
+ const { projectPath } = this
21
+ const templatePath = path.join(__dirname, 'files')
22
+ const projectDescriptor = await this.projectReader.read(this.options)
23
+ const projectType = await this.getProjectType();
24
+ const { for: forProfile } = projectDescriptor.cap
25
+
26
+ if (projectType === PROJECT_TYPE.java) {
27
+ const cdsrcJSONPath = path.join(projectPath, '.cdsrc.json')
28
+ const cdsTemplateFile = forProfile ? 'cds.cdsrc.json.hbs' : 'cds.cdsrc.json'
29
+ const cdsTemplatePath = path.join(templatePath, cdsTemplateFile)
30
+ await mergeJSON(cdsrcJSONPath, cdsTemplatePath, projectDescriptor)
31
+ } else if (projectType === PROJECT_TYPE.nodejs) {
32
+ const packageJSONPath = path.join(projectPath, 'package.json')
33
+ const cdsTemplateFile = forProfile ? 'cds.package.json.hbs' : 'cds.package.json'
34
+ const cdsTemplatePath = path.join(templatePath, cdsTemplateFile)
35
+ await mergeJSON(packageJSONPath, cdsTemplatePath, projectDescriptor)
36
+ const dependenciesTemplatePath = path.join(templatePath, 'dependencies.package.json')
37
+ await mergeJSON(packageJSONPath, dependenciesTemplatePath)
38
+ }
39
+
40
+ await this.runDependentMerging()
12
41
  }
13
42
 
14
43
  async runDependentMerging() {
15
44
  const projectDescriptor = await this.projectReader.read(this.options)
16
- const { isMultitenant, isExtensible, hasMtaDeployment, hasHelmDeployment, isNodejs, isJava } = projectDescriptor.cap
45
+ const { isMultitenant, isExtensible, hasMta, hasHelm, isNodejs, isJava } = projectDescriptor.cap
17
46
 
18
47
  const cds = require('../../../../lib/compile')
19
48
  const xsSecurity = await (async () => { try {
@@ -30,9 +59,9 @@ module.exports = class XsuaaTemplate extends TemplateBase {
30
59
  }],
31
60
  }))}
32
61
  const xsSecurityPath = path.join(this.projectPath, 'xs-security.json')
33
- await this.templateUtil.mergeJSON(xsSecurityPath, xsSecurity, projectDescriptor, mergingSemantics)
62
+ await mergeJSON(xsSecurityPath, xsSecurity, projectDescriptor, mergingSemantics)
34
63
 
35
- if (hasMtaDeployment) {
64
+ if (hasMta) {
36
65
  const srv = isNodejs ? srvNode : srvJava
37
66
  const additions = [srv, xsuaa]
38
67
  if (isMultitenant && isJava) additions.push(mtxSidecar)
@@ -47,7 +76,7 @@ module.exports = class XsuaaTemplate extends TemplateBase {
47
76
  into: [mtxSidecar, 'requires', 'name']
48
77
  })
49
78
 
50
- await this.templateUtil.mergeYAML(
79
+ await mergeYAML(
51
80
  mtaYAMLPath,
52
81
  `${__dirname}/files/mta.yaml.hbs`,
53
82
  projectDescriptor,
@@ -58,15 +87,18 @@ module.exports = class XsuaaTemplate extends TemplateBase {
58
87
  )
59
88
  }
60
89
 
61
- if (hasHelmDeployment) {
62
- await fs.copy(path.join(__dirname, 'files', 'xsuaa.yaml'), path.join(this.projectPath, 'chart', 'templates', 'xsuaa.yaml'))
63
- await this.templateUtil.mergeYAML(
90
+ if (hasHelm) {
91
+ await copy(
92
+ path.join(__dirname, 'files', 'xsuaa.yaml'),
93
+ path.join(this.projectPath, 'chart', 'templates', 'xsuaa.yaml')
94
+ )
95
+ await mergeYAML(
64
96
  path.join(this.projectPath, 'chart', 'values.yaml'),
65
97
  path.join(__dirname, 'files', 'values.yaml.hbs'),
66
98
  projectDescriptor, { forceOverwrite: true }
67
99
  )
68
100
  // REVISIT: Shared xs-security.json location for Helm and MTA?
69
- await fs.copy(
101
+ await copy(
70
102
  path.join(this.projectPath, 'xs-security.json'),
71
103
  path.join(this.projectPath, 'chart', 'xs-security.json')
72
104
  )
@@ -86,33 +118,4 @@ module.exports = class XsuaaTemplate extends TemplateBase {
86
118
  await extensibilityTemplate.runDependentMerging()
87
119
  }
88
120
  }
89
-
90
- async run() {
91
- const { projectPath } = this
92
- const templatePath = path.join(__dirname, 'files')
93
- const projectDescriptor = await this.projectReader.read(this.options)
94
- const { for: forProfile } = projectDescriptor.cap
95
-
96
- const projectType = await this.getProjectType();
97
- switch (projectType) {
98
- case PROJECT_TYPE.java: {
99
- const cdsrcJSONPath = path.join(projectPath, '.cdsrc.json')
100
- const cdsTemplateFile = forProfile ? 'cds.cdsrc.json.hbs' : 'cds.cdsrc.json'
101
- const cdsTemplatePath = path.join(templatePath, cdsTemplateFile)
102
- await this.templateUtil.mergeJSON(cdsrcJSONPath, cdsTemplatePath, projectDescriptor)
103
- break
104
- }
105
- case PROJECT_TYPE.nodejs: {
106
- const packageJSONPath = path.join(projectPath, 'package.json')
107
- const cdsTemplateFile = forProfile ? 'cds.package.json.hbs' : 'cds.package.json'
108
- const cdsTemplatePath = path.join(templatePath, cdsTemplateFile)
109
- await this.templateUtil.mergeJSON(packageJSONPath, cdsTemplatePath, projectDescriptor)
110
- const dependenciesTemplatePath = path.join(templatePath, 'dependencies.package.json')
111
- await this.templateUtil.mergeJSON(packageJSONPath, dependenciesTemplatePath)
112
- break
113
- }
114
- }
115
-
116
- await this.runDependentMerging()
117
- }
118
121
  }
@@ -28,41 +28,6 @@ export interface CDSGenerator {
28
28
  uiConfig?: any;
29
29
  }
30
30
 
31
-
32
- /**
33
- * An interface providing logging functionality.
34
- */
35
- export interface Logger {
36
- /**
37
- * True if logger is in debug mode
38
- */
39
- isDebug: boolean;
40
- /**
41
- * Writes a debug message to log.
42
- * @param message the message to write to log
43
- */
44
- debug(message: string): void;
45
-
46
- /**
47
- * Writes a message to log.
48
- * @param message the message to write to log
49
- */
50
- log(message: string): void;
51
-
52
- /**
53
- * Writes a warning message to log.
54
- * @param message the message to write to log
55
- */
56
- warn(message: string): void;
57
-
58
- /**
59
- * Writes an error to log.
60
- * @param Error the error to write to log
61
- */
62
- error(error: Error): void;
63
- }
64
-
65
-
66
31
  /**
67
32
  * This is a helper interface to provide support for different file system implementations.
68
33
  * Depending on the scenario different file systems will be used, e.g. Yeoman vs. native FS.
@@ -129,30 +94,6 @@ export interface FsUtil {
129
94
  * @param skipFileLog do not log files if true
130
95
  */
131
96
  copy(source: string, destination: string, options?: any, skipFileLog?: boolean): Promise<void>;
132
-
133
- /**
134
- * Checks if given path exists.
135
- * @param filePath the absolute path
136
- * @returns true if given path exists, otherwise false
137
- */
138
- pathExists(filePath: string): Promise<boolean>;
139
-
140
- /*
141
- * Methods mapping to fs-extra
142
- */
143
- readdir(filePath: string): Promise<string[]>;
144
-
145
- mkdirp(folderPath: string): Promise<void>;
146
-
147
- stat(filePath: string): Promise<any>;
148
-
149
- /*
150
- * Helper methods
151
- */
152
- hasContent(folderPath: string): Promise<boolean>;
153
-
154
- getTouchedFiles(): string[];
155
-
156
97
  }
157
98
 
158
99
  /**
@@ -1,10 +1,10 @@
1
1
  const cp = require('child_process');
2
2
  const os = require('os');
3
+ const cds = require('../../cds')
4
+ const LOG = cds.log('cds')
3
5
 
4
6
  const { IS_WIN } = require('../constants');
5
7
 
6
- const { nullLogger } = require('./logger');
7
-
8
8
  class CommandUtil {
9
9
 
10
10
  /**
@@ -13,30 +13,29 @@ class CommandUtil {
13
13
  * @param cmd command
14
14
  * @param args command args
15
15
  * @param options spawn options
16
- * @param logger logger to use
17
16
  * @param collectResult if true, return complete console output as promise resolve value
18
17
  * this might result in a huge string!
19
18
  *
20
19
  * @returns Promise
21
20
  */
22
- async spawnCommand(cmd, args, options = {}, logger = nullLogger, collectResult = false) {
21
+ async spawnCommand(cmd, args, options = {}, collectResult = false) {
23
22
  args = this._sanitizeArgs(args);
24
23
  return new Promise((resolve, reject) => {
25
- logger.debug(`[spawn] ${cmd} ${args.join(' ')}`);
24
+ LOG.debug(`[spawn] ${cmd} ${args.join(' ')}`);
26
25
 
27
26
  options.env = options.env || process.env;
28
27
 
29
28
  const child = this._getChildProcess(cmd, args, options);
30
29
 
31
30
  // use inplace methods to ensure logger is called in context
32
- const stdLogBuffer = new LogBuffer((chunk) => logger.log(chunk), collectResult);
31
+ const stdLogBuffer = new LogBuffer((chunk) => LOG.info(chunk), collectResult);
33
32
  child.stdout.on('data', (chunk) => {
34
33
  stdLogBuffer.handleChunk(chunk);
35
34
  });
36
35
 
37
36
  // use inplace methods to ensure logger is called in context
38
37
  // collect error log in case of Win to handle command not found (ENOENT),
39
- const errLogBuffer = new LogBuffer((chunk) => logger.error(chunk), (IS_WIN || collectResult));
38
+ const errLogBuffer = new LogBuffer((chunk) => LOG.error(chunk), (IS_WIN || collectResult));
40
39
  child.stderr.on('data', (chunk) => {
41
40
  errLogBuffer.handleChunk(chunk);
42
41
  });
@@ -1,127 +1,41 @@
1
- const fs = require('fs').promises;
2
- const path = require('path');
3
-
4
- const {yaml:YAML} = require('@sap/cds-foss')
1
+ const { yaml: YAML } = require('@sap/cds-foss')
5
2
  const JSONC = require('../../util/jsonc');
3
+ const { read, write } = require('../../cds').utils;
6
4
 
7
- const UTF_8 = 'utf-8';
8
-
9
- /**
10
- * this util implements FsUtil declared in ../types.d.ts
11
- * the interface FsUtil is also used by @sap/generator-cap-project
12
- */
13
- module.exports = class FsUtil {
14
-
15
- constructor() {
16
- this.touchedFiles = new Set();
17
- }
18
-
19
- async writeFile(filepath, content, skipFileLog = false) {
20
- if (!skipFileLog) {
21
- this._addTouchedFile(filepath);
22
- }
23
- await fs.mkdir(path.dirname(filepath), { recursive: true })
24
- await fs.writeFile(filepath, content, UTF_8);
25
- }
26
-
27
- async writeJSON(filepath, object, options = { spaces: 2 }, skipFileLog = false) {
28
- const content = JSON.stringify(object, null, options.spaces)
29
- await this.writeFile(filepath, content, skipFileLog)
30
- }
31
-
32
- async writeYAML(filepath, yaml, skipFileLog = false) {
33
- await this.writeFile(filepath, YAML.stringify(yaml, { collectionStyle: 'block' }), skipFileLog);
34
- }
35
-
36
- async readFile(src) {
37
- return await fs.readFile(src, UTF_8);
38
- }
39
-
40
- async readJSON(src, projectDescriptor) {
41
- const file = await this.readFile(src);
42
- if (projectDescriptor) {
43
- const Mustache = require('mustache');
44
- const renderedFile = Mustache.render(file, projectDescriptor);
45
- return JSON.parse(renderedFile);
46
- }
47
- return JSON.parse(file)
48
- }
49
-
50
- async readJSONC(src) {
51
- const fileContents = await this.readFile(src);
52
- return JSONC.parse(fileContents);
53
- }
5
+ module.exports = new class FsUtil {
54
6
 
55
7
  async readYAML(src, projectDescriptor) {
56
- let file;
8
+ let file
57
9
  try {
58
- file = await this.readFile(src);
10
+ file = await read(src, 'utf8')
59
11
  } catch (e) {
60
- if (e.code === 'ENOENT') return undefined;
61
- throw e;
12
+ if (e.code === 'ENOENT') return undefined
13
+ throw e
62
14
  }
63
15
  if (projectDescriptor) {
64
- const Mustache = require('mustache');
65
- const renderedFile = Mustache.render(file, projectDescriptor);
66
- return YAML.parseDocument(renderedFile);
67
- }
68
- return YAML.parseDocument(file);
69
- }
70
-
71
- // eslint-disable-next-line no-unused-vars
72
- async copy(source, destination, options = {}, skipFileLog = false) {
73
- if (!skipFileLog) {
74
- this._addTouchedFile(destination);
75
- }
76
- if (fs.cp) { // Node.js >= 16.7
77
- await fs.cp(source, destination, { recursive: true })
78
- } else {
79
- await _copy(source, destination);
16
+ const Mustache = require('mustache')
17
+ const renderedFile = Mustache.render(file, projectDescriptor)
18
+ return YAML.parseDocument(renderedFile)
80
19
  }
20
+ return YAML.parseDocument(file)
81
21
  }
82
22
 
83
- async pathExists(filePath) {
84
- return fs.access(filePath).then(() => true).catch(() => false)
85
- }
86
-
87
- async readdir(filePath) {
88
- return await fs.readdir(filePath);
89
- }
90
-
91
- getTouchedFiles() {
92
- return Array.from(this.touchedFiles.keys());
93
- }
94
-
95
- async mkdirp(folderPath) {
96
- await fs.mkdir(folderPath, { recursive: true });
23
+ async writeYAML(filepath, yaml) {
24
+ const content = YAML.stringify(yaml, { collectionStyle: 'block' })
25
+ await write(filepath, content)
97
26
  }
98
27
 
99
- async stat(filePath) {
100
- return await fs.stat(filePath);
101
- }
102
-
103
- async hasContent(folderPath) {
104
- if (await this.pathExists(folderPath)) {
105
- const projectContent = await this.readdir(folderPath);
106
- return projectContent.length > 0;
28
+ async readJSON(src, projectDescriptor) {
29
+ const file = await read(src, 'utf8')
30
+ if (projectDescriptor) {
31
+ const Mustache = require('mustache')
32
+ const renderedFile = Mustache.render(file, projectDescriptor)
33
+ return JSON.parse(renderedFile)
107
34
  }
108
-
109
- return false;
35
+ return JSON.parse(file)
110
36
  }
111
37
 
112
- _addTouchedFile(filepath) {
113
- const relativeFilepath = path.relative('', filepath);
114
- this.touchedFiles.add(relativeFilepath);
115
- }
116
- }
117
-
118
- // Polyfill for Node.14: asynchronously copies the entire content from src to dest.
119
- async function _copy(src, dest) {
120
- if ((await fs.stat(src)).isDirectory()) {
121
- const entries = await fs.readdir(src)
122
- return Promise.all(entries.map(async each => _copy(path.join(src, each), path.join(dest, each))))
123
- } else {
124
- await fs.mkdir(path.dirname(dest), { recursive: true })
125
- return fs.copyFile(src, dest)
38
+ async readJSONC(src) {
39
+ return JSONC.parse(await read(src, 'utf8'))
126
40
  }
127
41
  }