@sap/cds-dk 7.1.0 → 7.2.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 (56) hide show
  1. package/bin/build.js +3 -3
  2. package/bin/cds.js +2 -1
  3. package/bin/compile/index.js +5 -1
  4. package/bin/gen.js +27 -0
  5. package/bin/help.js +2 -1
  6. package/bin/watch.js +3 -4
  7. package/bin/watched.js +2 -3
  8. package/lib/bind/bindingUtil.js +1 -0
  9. package/lib/build/buildTaskEngine.js +13 -17
  10. package/lib/build/buildTaskFactory.js +23 -27
  11. package/lib/build/buildTaskHandler.js +6 -12
  12. package/lib/build/buildTaskProviderFactory.js +9 -12
  13. package/lib/build/constants.js +2 -1
  14. package/lib/build/index.js +1 -1
  15. package/lib/build/provider/buildTaskHandlerInternal.js +2 -2
  16. package/lib/build/provider/buildTaskProviderInternal.js +15 -25
  17. package/lib/build/provider/fiori/index.js +4 -3
  18. package/lib/build/provider/hana/index.js +14 -7
  19. package/lib/build/provider/java/index.js +2 -2
  20. package/lib/build/provider/nodejs/index.js +51 -18
  21. package/lib/build/util.js +11 -19
  22. package/lib/compile/openapi/csdl2openapi.js +30 -21
  23. package/lib/compile/openapi/index.js +7 -3
  24. package/lib/import/common.js +1 -1
  25. package/lib/import/message.js +6 -1
  26. package/lib/import/odata/metadataconverter/MetadataConverter.js +13 -9
  27. package/lib/import/odata/v4parser.js +26 -12
  28. package/lib/init/constants.js +6 -11
  29. package/lib/init/index.js +84 -71
  30. package/lib/init/template/_merging/registry-mta.js +0 -12
  31. package/lib/init/template/approuter/files/mta.yaml.hbs +1 -1
  32. package/lib/init/template/approuter/index.js +7 -6
  33. package/lib/init/template/cf-manifest/files/services-manifest.yml.hbs +0 -5
  34. package/lib/init/template/cf-manifest/index.js +2 -2
  35. package/lib/init/template/h2/index.js +16 -0
  36. package/lib/init/template/hana/index.js +2 -3
  37. package/lib/init/template/helm/chart/values.root.schema.json +0 -5
  38. package/lib/init/template/helm/chart/values.schema.json +0 -4
  39. package/lib/init/template/helm/index.js +1 -1
  40. package/lib/init/template/lint/index.js +3 -7
  41. package/lib/init/template/multitenancy/files/package.json.hbs +0 -3
  42. package/lib/init/template/multitenancy/index.js +2 -0
  43. package/lib/init/template/nodejs/index.js +3 -3
  44. package/lib/init/template/pipeline/index.js +2 -4
  45. package/lib/init/template/sample/index.js +5 -7
  46. package/lib/init/template/sqlite/index.js +8 -3
  47. package/lib/init/template/tiny-sample/index.js +16 -30
  48. package/lib/init/util/mvn.js +25 -1
  49. package/lib/init/util/projectReader.js +3 -7
  50. package/lib/init/util/template.js +7 -6
  51. package/lib/watch/node-watch.js +6 -1
  52. package/npm-shrinkwrap.json +46 -84
  53. package/package.json +5 -4
  54. package/lib/init/template/auditlog/files/mta.yaml.hbs +0 -14
  55. package/lib/init/template/auditlog/files/package.json.hbs +0 -27
  56. package/lib/init/template/auditlog/index.js +0 -74
package/lib/init/index.js CHANGED
@@ -3,7 +3,12 @@ const path = require('path');
3
3
  const term = require('../util/term');
4
4
 
5
5
  const { OPTIONS, COMMAND_INIT, PROJECT_FILES, REGEX_PROJECT_NAME } = require('./constants')
6
- const { NODEJS, JAVA, HANA, MTA,PIPELINE, TINY_SAMPLE, CF_MANIFEST } = OPTIONS
6
+ const {
7
+ NODEJS, JAVA,
8
+ HANA, APPROUTER, XSUAA, KIBANA, ENTERPRISE_MESSAGING,
9
+ MTA, HELM, MULTITENANCY, PIPELINE,
10
+ TINY_SAMPLE, SAMPLE
11
+ } = OPTIONS
7
12
 
8
13
  const cds = require('../cds'), { exists, readdir } = cds.utils
9
14
  const DEBUG = /\b(y|all|cli)\b/.test(process.env.DEBUG) ? console.debug : undefined
@@ -12,77 +17,86 @@ module.exports = class CDSGenerator {
12
17
  constructor() {
13
18
  this.cwd = process.cwd();
14
19
 
15
- this.uiConfig = [
16
- {
17
- title: `Project Name`,
18
- description: `Enter your project name.`,
19
- default: '',
20
- target: 'projectName',
21
- validate: async (value) => {
22
- try {
23
- cds.root = path.resolve(this.cwd, value || '.');
24
-
25
- await this._validateProjectName(value);
26
- await this._validateProjectFolder(path.join(this.cwd, value), this.cwd);
27
-
28
- return true;
29
- } catch (err) {
30
- return err;
31
- }
32
- },
33
- guiOptions: {
34
- hint: 'This name is restricted to certain characters. A valid project name is compatible across platforms.',
35
- mandatory: true
36
- }
37
- },
38
- {
39
- title: `Type`,
40
- description: `Select your runtime.`,
41
- default: NODEJS,
42
- choices: [
43
- { name: 'Node.js', value: NODEJS },
44
- { name: 'Java', value: JAVA }
45
- ],
46
- multiple: false,
47
- target: 'add',
48
- guiOptions: {
49
- hint: `The preferred runtime can't be changed afterwards. To use a different runtime, create a new project.`,
50
- mandatory: true
51
- }
52
- },
53
- {
54
- title: `Features`,
55
- description: `Add features to your project.`,
56
- default: '',
57
- choices: [
58
- { name: 'CI/CD Pipeline Integration', value: PIPELINE },
59
- { name: 'Configuration for SAP HANA Deployment', value: HANA },
60
- { name: 'MTA based SAP Business Technology Platform Deployment', value: MTA },
61
- // { name: 'Multitenancy', value: mtx },
62
- { name: `Cloud Foundry native Deployment`, value: CF_MANIFEST }
63
- // { name: `CDS Linter for custom rules`, value: lint },
64
- // { name: `CDS Linter for custom rules with sample`, value: lintDev }
65
- ],
66
- multiple: true,
67
- target: 'add',
68
- guiOptions: {
69
- hint: `Choose any combination of features enriching the capabilities of your project. You can also add features later with ${term.bold('cds add')}`
20
+ this.uiConfig = [{
21
+ title: 'Project Name',
22
+ description: 'Enter your project name.',
23
+ default: '',
24
+ target: 'projectName',
25
+ validate: async (value) => {
26
+ try {
27
+ cds.root = path.resolve(this.cwd, value || '.');
28
+
29
+ await this._validateProjectName(value);
30
+ await this._validateProjectFolder(path.join(this.cwd, value), this.cwd);
31
+ } catch (e) {
32
+ return e
70
33
  }
34
+
35
+ return true;
71
36
  },
72
- {
73
- title: `Samples`,
74
- description: `Add sample content to your project.`,
75
- default: '',
76
- choices: [
77
- { name: 'Basic Sample Files', value: TINY_SAMPLE }
78
- ],
79
- multiple: true,
80
- target: 'add',
81
- guiOptions: {
82
- hint: 'Speed up your ramp-up phase with some sample files in your project.'
83
- }
37
+ guiOptions: {
38
+ hint: 'This name is restricted to certain characters. A valid project name is compatible across platforms.',
39
+ mandatory: true
40
+ }
41
+ }, {
42
+ title: 'Type',
43
+ description: `Select your runtime.`,
44
+ default: NODEJS,
45
+ choices: [
46
+ { name: 'Node.js', value: NODEJS },
47
+ { name: 'Java', value: JAVA }
48
+ ],
49
+ multiple: false,
50
+ target: 'add',
51
+ guiOptions: {
52
+ hint: `The preferred runtime can't be changed afterwards. To use a different runtime, create a new project.`,
53
+ mandatory: true
54
+ }
55
+ }, {
56
+ title: 'Features',
57
+ description: 'Choose productive runtime capabilities for your application.',
58
+ default: '',
59
+ choices: [
60
+ { name: 'SAP HANA Cloud', value: HANA },
61
+ { name: 'SAP Application Router', value: APPROUTER },
62
+ { name: 'User Authentication via XSUAA', value: XSUAA },
63
+ { name: 'Kibana Logging Dashboard', value: KIBANA },
64
+ { name: 'SAP BTP Event Mesh', value: ENTERPRISE_MESSAGING }
65
+ ],
66
+ multiple: true,
67
+ target: 'add',
68
+ guiOptions: {
69
+ hint: `Choose any combination of features enriching the capabilities of your project. You can also add features later with ${term.bold('cds add')}`
70
+ }
71
+ }, {
72
+ title: 'Deployment',
73
+ description: 'Choose which way to deploy your project.',
74
+ default: '',
75
+ choices: [
76
+ { name: 'Cloud Foundry: MTA Deployment', value: MTA },
77
+ { name: 'Kyma: Helm Deployment', value: HELM },
78
+ { name: 'Multitenancy', value: MULTITENANCY },
79
+ { name: 'CI/CD Pipeline Integration', value: PIPELINE },
80
+ ],
81
+ multiple: true,
82
+ target: 'add',
83
+ guiOptions: {
84
+ hint: `Choose any combination of features enriching the capabilities of your project. You can also add features later with ${term.bold('cds add')}`
85
+ }
86
+ }, {
87
+ title: 'Samples',
88
+ description: `Add sample content to your project.`,
89
+ default: '',
90
+ choices: [
91
+ { name: 'Minimal Sample', value: TINY_SAMPLE },
92
+ { name: 'Extended Sample with UI', value: SAMPLE }
93
+ ],
94
+ multiple: true,
95
+ target: 'add',
96
+ guiOptions: {
97
+ hint: 'Speed up your ramp-up phase with sample files in your project.'
84
98
  }
85
- ]
99
+ }]
86
100
  }
87
101
 
88
102
  /**
@@ -190,8 +204,7 @@ module.exports = class CDSGenerator {
190
204
  );
191
205
  const fuzzySearch = require('../../bin/util/fuzzySearch');
192
206
  const [bestMatch] = fuzzySearch(filename, entries);
193
- console.log(`Unknown facet '${term.bold(filename)}'. Did you mean ${term.bold(`cds add ${bestMatch}`)}?\n\nHaven't found the proper facet yet? Here are all supported facets:\n\n ${term.bold(entries.join('\n '))}\n`);
194
- process.exit(1);
207
+ throw `Unknown facet '${term.bold(filename)}'. Did you mean ${term.bold(`cds add ${bestMatch}`)}?\n\nHaven't found the proper facet yet? Here are all supported facets:\n\n ${term.bold(entries.join('\n '))}\n`
195
208
  }
196
209
  throw err;
197
210
  }
@@ -60,17 +60,6 @@ const connectivity = {
60
60
  }]
61
61
  }
62
62
 
63
- const auditlog = {
64
- in: 'resources',
65
- where: [{
66
- property: 'type',
67
- isEqualTo: 'org.cloudfoundry.managed-service',
68
- }, {
69
- property: 'parameters.service',
70
- isEqualTo: 'auditlog-api',
71
- }]
72
- }
73
-
74
63
  const redis = {
75
64
  in: 'resources',
76
65
  where: [{
@@ -260,7 +249,6 @@ module.exports = {
260
249
  srvJava4,
261
250
  approuter,
262
251
  xsuaa,
263
- auditlog,
264
252
  destination,
265
253
  connectivity,
266
254
  enterpriseMessaging,
@@ -19,7 +19,7 @@ modules:
19
19
 
20
20
  - name: {{appName}}
21
21
  type: approuter.nodejs
22
- path: {{& appPath}} # from cds.env.folders. Consider also cds.env.build.target -> gen/app
22
+ path: {{& approuterPath }}
23
23
  parameters:
24
24
  keep-existing-routes: true
25
25
  disk-quota: 256M
@@ -16,7 +16,8 @@ const { copyAndTrack, parseMd5File, writeMd5File } = require('../../util/md5')
16
16
  module.exports = class ApprouterTemplate extends require('../templateBase') {
17
17
 
18
18
  static hasFacet(env) {
19
- return exists(join(env.folders.app, 'xs-app.json'))
19
+ return exists(join(env.folders.app, 'router', 'xs-app.json')) ||
20
+ exists(join(env.folders.app, 'xs-app.json'))
20
21
  }
21
22
 
22
23
  getDependencies() {
@@ -28,16 +29,16 @@ module.exports = class ApprouterTemplate extends require('../templateBase') {
28
29
  }
29
30
 
30
31
  async run() {
31
- const { appPath = 'app' } = await readProject()
32
- const appPackageJSONPath = join(appPath, 'package.json')
32
+ const { approuterPath } = await readProject()
33
+ const appPackageJSONPath = join(approuterPath, 'package.json')
33
34
  await mergeJSON(appPackageJSONPath, join(__dirname, 'files', 'package.json'))
34
35
  await sort(appPackageJSONPath, 'dependencies')
35
- await mergeJSON(join(appPath, 'default-env.json'), join(__dirname, 'files', 'default-env.json'))
36
+ await mergeJSON(join(approuterPath, 'default-env.json'), join(__dirname, 'files', 'default-env.json'))
36
37
  }
37
38
 
38
39
  async runDependentMerging(context = {}) {
39
40
  const project = await readProject()
40
- const { isNodejs, isJava, isExtensible, isMultitenant, hasMta, hasHelm, srvPath, appPath } = project
41
+ const { isNodejs, isJava, isExtensible, isMultitenant, hasMta, hasHelm, srvPath, approuterPath } = project
41
42
 
42
43
  if (hasMta) {
43
44
  const srv = (isNodejs ? srvNode4 : srvJava4)(srvPath)
@@ -116,7 +117,7 @@ module.exports = class ApprouterTemplate extends require('../templateBase') {
116
117
  if (isIndependentCommand) await writeMd5File(join('chart', '.cds-add-helm-files.md5'), context.newTrackingData);
117
118
  }
118
119
 
119
- const xsAppPath = join(appPath, 'xs-app.json')
120
+ const xsAppPath = join(approuterPath, 'xs-app.json')
120
121
  const additions = isExtensible ? [{ ...approuterExtensibility, at: 0 }] : []
121
122
  await mergeJSON(xsAppPath, join(__dirname, 'files', 'xs-app.json.hbs'), project, { additions })
122
123
  }
@@ -20,8 +20,3 @@ create-services:
20
20
  plan: application
21
21
  parameters: xs-security.json
22
22
  {{/hasXsuaa}}
23
- {{#hasAuditlog}}
24
- - name: {{appName}}-auditlog
25
- broker: auditlog
26
- plan: application
27
- {{/hasAuditlog}}
@@ -2,7 +2,7 @@ const { join } = require('path')
2
2
  const cds = require('../../../cds')
3
3
  const { exists } = require('../../../cds').utils
4
4
  const { readProject } = require('../../util/projectReader')
5
- const { copyFiles } = require('../../util/template')
5
+ const { renderAndCopy } = require('../../util/template')
6
6
  const MANIFEST_FILE = 'manifest.yml'
7
7
  const SERVICES_MANIFEST_FILE = 'services-manifest.yml'
8
8
 
@@ -20,6 +20,6 @@ module.exports = class CfManifestTemplate extends require('../templateBase') {
20
20
 
21
21
  async run() {
22
22
  const project = await readProject()
23
- await copyFiles(join(__dirname, 'files'), cds.root, project, true)
23
+ await renderAndCopy(join(__dirname, 'files'), cds.root, project)
24
24
  }
25
25
  }
@@ -0,0 +1,16 @@
1
+ const mvn = require('../../util/mvn')
2
+ const { readProject } = require('../../util/projectReader')
3
+ const { H2 } = require('../../constants').OPTIONS
4
+
5
+ module.exports = class H2Template extends require('../templateBase') {
6
+
7
+ async canRun() {
8
+ const { isNodejs } = await readProject()
9
+ if (isNodejs) throw `'cds add ${H2}' is not available for Node.js`
10
+ return true
11
+ }
12
+
13
+ async run() {
14
+ await mvn.add(H2)
15
+ }
16
+ }
@@ -1,11 +1,10 @@
1
1
  const { join } = require('path')
2
2
  const cds = require('../../../cds')
3
- const { read, write, exists, rmdir } = cds.utils
3
+ const { read, write, exists, rmdir, copy } = cds.utils
4
4
  const { readProject } = require('../../util/projectReader')
5
5
  const { mergeJSON, mergeYAML, removeFromYAML, removeFromYAMLArray } = require('../../util/merge')
6
6
  const mvn = require('../../util/mvn')
7
7
  const { parseMd5File, writeMd5File } = require('../../util/md5')
8
- const { copyFiles } = require('../../util/template')
9
8
 
10
9
  const { OPTIONS: { JAVA } } = require('../../constants')
11
10
 
@@ -33,7 +32,7 @@ module.exports = class HanaTemplate extends require('../templateBase') {
33
32
  await mergeJSON(undeployJSONPath, undeployJSONTemplatePath)
34
33
 
35
34
  if (isJava) {
36
- await copyFiles(join(__dirname, 'files', 'db'), db.folder, {}, cds.cli.options.force)
35
+ await copy(join(__dirname, 'files', 'db')).to(db.folder)
37
36
  // REVISIT: shouldn't behave differently during cds init
38
37
  // if called during cds init the project generation call to AT will add settings
39
38
  if (!cds.cli.options.add.has(JAVA)) await mvn.execMvn(mvn.getAddHanaCmdArgs())
@@ -37,11 +37,6 @@
37
37
  "description": "Service Instance",
38
38
  "$ref": "./charts/service-instance/values.schema.json"
39
39
  },
40
- "auditlog": {
41
- "$id": "#/properties/auditlog",
42
- "description": "Service Instance",
43
- "$ref": "./charts/service-instance/values.schema.json"
44
- },
45
40
  "destination": {
46
41
  "$id": "#/properties/destination",
47
42
  "description": "Service Instance",
@@ -66,10 +66,6 @@
66
66
  "$id": "#/properties/xsuaa",
67
67
  "description": "Service Instance"
68
68
  },
69
- "auditlog": {
70
- "$id": "#/properties/auditlog",
71
- "description": "Service Instance"
72
- },
73
69
  "destination": {
74
70
  "$id": "#/properties/destination",
75
71
  "description": "Service Instance"
@@ -14,7 +14,7 @@ module.exports = class HelmTemplate extends require('../templateBase') {
14
14
  }
15
15
 
16
16
  getRelatedFacets() {
17
- return ['hana', 'xsuaa', 'auditlog', 'enterprise-messaging', 'destination' , 'multitenancy', 'extensibility', 'approuter', 'connectivity']
17
+ return ['hana', 'xsuaa', 'enterprise-messaging', 'destination' , 'multitenancy', 'extensibility', 'approuter', 'connectivity']
18
18
  }
19
19
 
20
20
  static hasFacet() {
@@ -5,7 +5,7 @@ const term = require("../../../util/term");
5
5
  const checks = require("../../../lint/checks");
6
6
  const io = require("../../../lint/io");
7
7
  const readline = require("readline");
8
- const { copyFiles } = require('../../util/template')
8
+ const { renderAndCopy } = require('../../util/template')
9
9
  const { LINT_DEV, LINT_GLOBAL } = require("../../constants").OPTIONS;
10
10
  const { getConfigPath, getFileExtensions } = require("@sap/eslint-plugin-cds/lib/api");
11
11
  const cds = require("../../../cds");
@@ -62,10 +62,10 @@ module.exports = class LintTemplate extends require('../templateBase') {
62
62
  await this._generateEslintDirs();
63
63
 
64
64
  if (!exists(".eslint/rules/no-entity-moo.js")) {
65
- await this._copyFromTemplate(".eslint/rules", this.rulesPath);
65
+ await renderAndCopy(".eslint/rules", this.rulesPath);
66
66
  }
67
67
  if (!exists(".eslint/tests/no-entity-moo.test.js")) {
68
- await this._copyFromTemplate(".eslint/tests", this.testsPath);
68
+ await renderAndCopy(".eslint/tests", this.testsPath);
69
69
  }
70
70
  }
71
71
 
@@ -150,10 +150,6 @@ module.exports = class LintTemplate extends require('../templateBase') {
150
150
  await mkdirp(this.testsPath);
151
151
  }
152
152
 
153
- async _copyFromTemplate(source, dest) {
154
- await copyFiles(source, dest, {}, true);
155
- }
156
-
157
153
  async _addEslintPluginConfig() {
158
154
  let configPath = getConfigPath(cds.root);
159
155
  if (!configPath) {
@@ -7,9 +7,6 @@
7
7
  {{/isNodejs}}
8
8
  {{#isJava}}
9
9
  "profiles": ["with-mtx-sidecar", "java"],
10
- "build": {
11
- "target": "."
12
- },
13
10
  {{/isJava}}
14
11
  {{#isNodejs}}
15
12
  "profile": "with-mtx-sidecar",
@@ -2,6 +2,7 @@ const { join } = require('path')
2
2
  const cds = require('../../../cds')
3
3
  const { exists, read, write } = cds.utils
4
4
  const { APPROUTER, HANA, KIBANA } = require('../../constants').OPTIONS
5
+ const mvn = require('../../util/mvn')
5
6
  const { readProject } = require('../../util/projectReader')
6
7
  const { mergeJSON, mergeYAML, sort } = require('../../util/merge')
7
8
  const { copyAndTrack, parseMd5File, writeMd5File } = require('../../util/md5')
@@ -35,6 +36,7 @@ module.exports = class MultitenancyTemplate extends require('../templateBase') {
35
36
  const packageJson = await read('package.json')
36
37
  packageJson.workspaces = ['mtx/sidecar']
37
38
  await write('package.json', packageJson, { spaces: 2 })
39
+ await mvn.execMvn(mvn.getAddArgs('mtx'))
38
40
  }
39
41
  if (isNodejs) await sort('package.json', 'dependencies')
40
42
  await copyRenderedJSON(join(__dirname, 'files', 'package.sidecar.json.hbs'), join('mtx', 'sidecar', 'package.json'), project)
@@ -3,12 +3,12 @@ const cds = require('../../../cds')
3
3
  const { exists, mkdirp, path } = cds.utils
4
4
  const { URLS, OPTIONS: { NODEJS, JAVA }, COMMAND_ADD } = require('../../constants')
5
5
  const term = require('../../../util/term')
6
- const { copyFiles } = require('../../util/template')
6
+ const { renderAndCopy } = require('../../util/template')
7
7
 
8
8
  module.exports = class NodejsTemplate extends require('../templateBase') {
9
9
 
10
10
  static hasFacet() {
11
- return !exists('pom.xml') || cds.cli.options?.add?.has(NODEJS)
11
+ return !exists('pom.xml') && !cds.cli.options?.add?.has(JAVA)
12
12
  }
13
13
 
14
14
  async canRun() {
@@ -23,7 +23,7 @@ module.exports = class NodejsTemplate extends require('../templateBase') {
23
23
 
24
24
  async run() {
25
25
  const { db, srv, app } = (await this.getEnv()).folders
26
- await copyFiles(join(__dirname, 'files'), cds.root, { projectName: path.basename(cds.root) }, cds.cli.options.force)
26
+ await renderAndCopy(join(__dirname, 'files'), cds.root, { projectName: path.basename(cds.root) })
27
27
  await Promise.all([db, srv, app].map(p => mkdirp(p)))
28
28
  }
29
29
 
@@ -1,12 +1,10 @@
1
1
  const { join } = require('path');
2
2
  const cds = require('../../../cds')
3
- const { exists } = cds.utils
4
- const { copyFiles } = require('../../util/template')
3
+ const { exists, copy } = cds.utils
5
4
  const { URLS } = require('../../constants')
6
5
 
7
6
  module.exports = class PipelineTemplate extends require('../templateBase') {
8
7
 
9
-
10
8
  async canRun() {
11
9
  if (cds.cli.options.force) {
12
10
  return true;
@@ -20,7 +18,7 @@ module.exports = class PipelineTemplate extends require('../templateBase') {
20
18
  }
21
19
 
22
20
  async run() {
23
- await copyFiles(join(__dirname, 'files'), cds.root, {}, true);
21
+ await copy(join(__dirname, 'files')).to(cds.root)
24
22
  }
25
23
 
26
24
  async finalize() {
@@ -1,7 +1,6 @@
1
1
  const { join } = require('path')
2
- const cds = require('../../../cds'), { exists } = cds.utils
2
+ const cds = require('../../../cds'), { exists, copy } = cds.utils
3
3
  const { readProject } = require('../../util/projectReader')
4
- const { copyFiles } = require('../../util/template')
5
4
 
6
5
  module.exports = class SampleTemplate extends require('../templateBase') {
7
6
 
@@ -14,12 +13,11 @@ module.exports = class SampleTemplate extends require('../templateBase') {
14
13
  async run() {
15
14
  const { db, srv, app } = (await this.getEnv()).folders
16
15
  const language = exists('pom.xml') ? 'java' : 'nodejs'
17
- const { force } = cds.cli.options
18
16
  await Promise.all([
19
- copyFiles(join(__dirname, 'files', 'db'), db, {}, force),
20
- copyFiles(join(__dirname, 'files', 'app'), app, {}, force),
21
- copyFiles(join(__dirname, 'files', 'srv'), srv, {}, force),
22
- copyFiles(join(__dirname, 'files', language), srv, {}, force)
17
+ copy(join(__dirname, 'files', 'db')).to(db),
18
+ copy(join(__dirname, 'files', 'app')).to(app),
19
+ copy(join(__dirname, 'files', 'srv')).to(srv),
20
+ copy(join(__dirname, 'files', language)).to(srv)
23
21
  ])
24
22
  }
25
23
  }
@@ -1,6 +1,7 @@
1
1
  const { join } = require('path')
2
2
  const cds = require('../../../cds')
3
3
  const { read } = cds.utils
4
+ const mvn = require('../../util/mvn')
4
5
  const { readProject } = require('../../util/projectReader')
5
6
  const { mergeJSON } = require('../../util/merge')
6
7
 
@@ -8,8 +9,12 @@ module.exports = class SQLiteTemplate extends require('../templateBase') {
8
9
 
9
10
  async run() {
10
11
  const project = await readProject()
11
- const { configFile } = project
12
- project.shortcut = !(await read(configFile)).cds?.requires?.db?.kind
13
- await mergeJSON(configFile, join(__dirname, 'files', `package.json.hbs`), project)
12
+ const { isNodejs, isJava, configFile } = project
13
+ if (isNodejs) {
14
+ project.shortcut = !(await read(configFile)).cds?.requires?.db?.kind
15
+ await mergeJSON(configFile, join(__dirname, 'files', `package.json.hbs`), project)
16
+ } else if (isJava) {
17
+ await mvn.add('sqlite')
18
+ }
14
19
  }
15
20
  }
@@ -1,39 +1,25 @@
1
1
  const { join } = require('path')
2
- const cds = require('../../../cds')
3
- const { copyFiles } = require('../../util/template')
4
- const commandUtil = require('../../../util/command')
5
- const mvnArchetypes = require('../../util/mvn')
6
- const term = require('../../../util/term')
7
- const { PROJECT_TYPE: { java, nodejs }, OPTIONS: { JAVA }, URLS } = require('../../constants')
2
+ const cds = require('../../../../lib/cds'), { copy } = cds.utils
3
+ const { renderAndCopy } = require('../../util/template')
4
+ const mvn = require('../../util/mvn')
5
+ const { readProject } = require('../../util/projectReader')
6
+ const { JAVA } = require('../../constants')
8
7
 
9
8
  module.exports = class TinySampleTemplate extends require('../templateBase') {
10
9
 
11
10
  async run() {
12
- switch (this.getProjectType()) {
13
- case java: return this._addJavaSamples()
14
- case nodejs: return this._addNodejsSamples()
15
- }
16
- }
17
-
18
- async _addJavaSamples() {
19
- if (!cds.cli.options.add.has(JAVA)) {
20
- const mvnAddSamplesArgs = mvnArchetypes.getAddSamplesCmdArgs()
21
- try {
22
- await commandUtil.spawnCommand('mvn', mvnAddSamplesArgs, { cwd: cds.root })
23
- const mvnAddTestsArgs = mvnArchetypes.getAddTestsCmdArgs()
24
- await commandUtil.spawnCommand('mvn', mvnAddTestsArgs, { cwd: cds.root })
25
- } catch (err) {
26
- if (err.code === 'ENOENT' && err.path === 'mvn') {
27
- throw `Maven executable 'mvn' not found, follow ${term.info(URLS.MAVEN_INSTALL_HELP)} and install Maven on your machine.`
28
- }
29
- throw err
11
+ const { isJava } = await readProject()
12
+ if (isJava) {
13
+ if (!cds.cli.options.add.has(JAVA)) {
14
+ await mvn.execMvn(mvn.getAddSamplesCmdArgs())
15
+ await mvn.execMvn(mvn.getAddTestsCmdArgs())
30
16
  }
17
+ } else {
18
+ const { db, srv } = (await this.getEnv()).folders
19
+ await Promise.all([
20
+ copy(join(__dirname, 'files', 'nodejs', 'db')).to(db),
21
+ renderAndCopy(join(__dirname, 'files', 'nodejs', 'srv'), srv, { dbFolder: db.replace(/[\\/]+$/, '') })
22
+ ])
31
23
  }
32
24
  }
33
-
34
- async _addNodejsSamples() {
35
- const { db, srv } = (await this.getEnv()).folders
36
- await copyFiles(join(__dirname, 'files', 'nodejs', 'db'), db, {}, cds.cli.options.force)
37
- await copyFiles(join(__dirname, 'files', 'nodejs', 'srv'), srv, { dbFolder: db.replace(/[\\/]+$/, '') }, cds.cli.options.force)
38
- }
39
25
  }
@@ -33,7 +33,6 @@ class MvnArchetypeUtil {
33
33
  }
34
34
 
35
35
  _finalize(params) {
36
- // `-DcdsVersion=3.0.0`,
37
36
  params.set(`-Dstyle.color`, `always`);
38
37
 
39
38
  params.set('-B');
@@ -48,6 +47,31 @@ class MvnArchetypeUtil {
48
47
  return Array.from(params, ([arg, val]) => val !== null && val !== undefined ? `${arg}=${val}` : arg)
49
48
  }
50
49
 
50
+ // REVISIT: make this only public API once mvn:addSample etc. have been moved to generic mvn:add
51
+ async add(feature) {
52
+ return this.execMvn(this.getAddArgs(feature))
53
+ }
54
+
55
+ getAddArgs(feature) {
56
+ const params = new Map();
57
+
58
+ params.set(`com.sap.cds:cds-maven-plugin:${MAVEN_ARCHETYPE_VERSION}:add`);
59
+ params.set(`-Dfeature`, feature)
60
+ const profile = cds.cli.options.for
61
+ params.set(`-Dprofile`, profile === 'production' ? 'cloud' : profile)
62
+
63
+ const { options } = cds.cli
64
+ if (options[JAVA_MVN]) {
65
+ this._scanMvnParams(options[JAVA_MVN], params);
66
+ }
67
+
68
+ if (options.force) {
69
+ params.set(`-Doverwrite`, true);
70
+ }
71
+
72
+ return this._finalize(params);
73
+ }
74
+
51
75
  getAddSamplesCmdArgs() {
52
76
  const params = new Map();
53
77
 
@@ -2,6 +2,7 @@ const cds = require('../../cds')
2
2
  const { join, resolve, basename } = require('path')
3
3
  const { fs, exists } = cds.utils
4
4
  const { parseXml } = require('./xml')
5
+ const { REGEX_JAVA_VERSION } = require('../constants')
5
6
  const DEBUG = cds.debug('cli')
6
7
 
7
8
  module.exports = new class ProjectReader {
@@ -18,12 +19,7 @@ module.exports = new class ProjectReader {
18
19
  if (exists('pom.xml')) {
19
20
  const { artifactId = [], description = [], version = [], properties = [] } = parseXml(resolve(cds.root, 'pom.xml')) ?? {}
20
21
  const v = version[0] === '${revision}' ? properties[0]?.revision[0] : version[0]
21
- if (v) {
22
- // check compliance with mta version format - copied from mbt error message
23
- if (/^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(-(0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(\.(0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*)?(\+[0-9a-zA-Z-]+(\.[0-9a-zA-Z-]+)*)?$/.test(v)) {
24
- this.appVersion = v
25
- }
26
- }
22
+ if (v && REGEX_JAVA_VERSION.test(v)) this.appVersion = v
27
23
  if (artifactId[0]) this.appName = this.appId = artifactId[0].split(/-parent/)[0]
28
24
  if (description[0]) this.appDescription = description[0]
29
25
  }
@@ -79,13 +75,13 @@ module.exports = new class ProjectReader {
79
75
  get isExtensible() { return _hasFacet('extensibility') },
80
76
  get hasHana() { return _hasFacet('hana') },
81
77
  get hasXsuaa() { return _hasFacet('xsuaa') },
82
- get hasAuditlog() { return _hasFacet('auditlog') },
83
78
  get hasApprouter() { return _hasFacet('approuter') },
84
79
  get hasDestination() { return _hasFacet('destination') },
85
80
  get hasHtml5Repo() { return _hasFacet('html5-repo') },
86
81
  get hasMta() { return _hasFacet('mta') },
87
82
  get hasHelm() { return _hasFacet('helm') },
88
83
  get appPath() { return env.folders.app ?? 'app' },
84
+ get approuterPath() { return join(env.folders.app ?? 'app', 'router') },
89
85
  get appVersion() { return appVersion },
90
86
  get appName() { return appName },
91
87
  get appId() { return appId },