@sap/cds-dk 6.8.2 → 7.0.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 (218) hide show
  1. package/bin/activate.js +15 -7
  2. package/bin/add.js +29 -15
  3. package/bin/bind.js +49 -116
  4. package/bin/build.js +114 -0
  5. package/bin/cds.js +67 -24
  6. package/bin/compile/index.js +2 -2
  7. package/bin/deploy/index.js +46 -39
  8. package/bin/deploy/to-hana.js +11 -8
  9. package/bin/deploy/to-postgres.js +8 -2
  10. package/bin/deploy/to-sqlite.js +0 -1
  11. package/bin/env.js +75 -41
  12. package/bin/eval.js +3 -3
  13. package/bin/extend.js +17 -10
  14. package/bin/help.js +22 -21
  15. package/bin/import.js +10 -7
  16. package/bin/init.js +38 -17
  17. package/bin/login.js +69 -55
  18. package/bin/logout.js +12 -9
  19. package/bin/migrate.js +10 -4
  20. package/bin/pull.js +12 -5
  21. package/bin/push.js +24 -13
  22. package/bin/repl.js +1 -0
  23. package/bin/run.js +25 -0
  24. package/bin/subscribe.js +13 -8
  25. package/bin/unsubscribe.js +15 -8
  26. package/bin/upgrade.js +15 -9
  27. package/bin/util/log.js +24 -0
  28. package/bin/version.js +124 -0
  29. package/bin/watch.js +1 -35
  30. package/bin/watched.js +39 -0
  31. package/lib/bind/KubernetesApiAccessor.js +2 -2
  32. package/lib/bind/bindingManager.js +1 -1
  33. package/lib/bind/bindingUtil.js +0 -9
  34. package/lib/bind/cfKeyProvider.js +10 -72
  35. package/lib/bind/index.js +114 -0
  36. package/lib/bind/kubernetesCredentialsProvider.js +2 -2
  37. package/lib/bind/userCdsrcJsonStorageProvider.js +7 -44
  38. package/lib/build/buildTaskEngine.js +355 -0
  39. package/lib/build/buildTaskFactory.js +284 -0
  40. package/lib/build/buildTaskHandler.js +240 -0
  41. package/lib/build/buildTaskProvider.js +22 -0
  42. package/lib/build/buildTaskProviderFactory.js +182 -0
  43. package/lib/build/constants.js +56 -0
  44. package/lib/build/index.js +21 -0
  45. package/lib/build/provider/buildTaskHandlerEdmx.js +83 -0
  46. package/lib/build/provider/buildTaskHandlerFeatureToggles.js +132 -0
  47. package/lib/build/provider/buildTaskHandlerInternal.js +228 -0
  48. package/lib/build/provider/buildTaskProviderInternal.js +370 -0
  49. package/lib/build/provider/fiori/index.js +167 -0
  50. package/lib/build/provider/hana/2migration.js +179 -0
  51. package/lib/build/provider/hana/index.js +522 -0
  52. package/lib/build/provider/hana/migrationtable.js +472 -0
  53. package/lib/build/provider/hana/template/.hdiconfig-all +163 -0
  54. package/lib/build/provider/hana/template/.hdiconfig-cloud +137 -0
  55. package/lib/build/provider/hana/template/.hdinamespace +4 -0
  56. package/lib/build/provider/hana/template/package.json +12 -0
  57. package/lib/build/provider/hana/template/undeploy.json +5 -0
  58. package/lib/build/provider/java/index.js +93 -0
  59. package/lib/build/provider/java-cf/index.js +1 -0
  60. package/lib/build/provider/mtx/index.js +37 -0
  61. package/lib/build/provider/mtx/resourcesTarBuilder.js +94 -0
  62. package/lib/build/provider/mtx-extension/index.js +131 -0
  63. package/lib/build/provider/mtx-sidecar/index.js +138 -0
  64. package/lib/build/provider/node-cf/index.js +1 -0
  65. package/lib/build/provider/nodejs/index.js +178 -0
  66. package/lib/build/util.js +263 -0
  67. package/lib/cds.js +9 -21
  68. package/lib/client/auth_manager.js +39 -16
  69. package/lib/client/helper/dependency_helper.js +7 -6
  70. package/lib/client/push.js +2 -1
  71. package/lib/client/settings_manager.js +10 -39
  72. package/lib/deploy/to-hana/hana.js +273 -0
  73. package/lib/deploy/to-hana/hdiDeployUtil.js +68 -0
  74. package/lib/deploy/to-hana/mtaUtil.js +171 -0
  75. package/lib/import/asyncapi/importAsyncAPI.js +3 -2
  76. package/lib/import/asyncapi/index.js +5 -2
  77. package/lib/import/asyncapi/parserContext.js +67 -26
  78. package/lib/import/asyncapi/utils.js +34 -3
  79. package/lib/import/common.js +40 -30
  80. package/lib/import/importapi.js +36 -35
  81. package/lib/index.js +12 -17
  82. package/lib/init/constants.js +36 -71
  83. package/lib/init/index.js +18 -52
  84. package/lib/init/template/_merging/registry-mta.js +21 -3
  85. package/lib/init/template/approuter/files/mta.yaml.hbs +29 -29
  86. package/lib/init/template/approuter/files/values.yaml.hbs +5 -5
  87. package/lib/init/template/approuter/files/xs-app.json.hbs +8 -2
  88. package/lib/init/template/approuter/index.js +7 -8
  89. package/lib/init/template/auditlog/files/mta.yaml.hbs +5 -5
  90. package/lib/init/template/auditlog/files/package.json.hbs +13 -13
  91. package/lib/init/template/auditlog/index.js +3 -3
  92. package/lib/init/template/cf-manifest/files/manifest.yml.hbs +22 -22
  93. package/lib/init/template/cf-manifest/files/services-manifest.yml.hbs +3 -3
  94. package/lib/init/template/connectivity/files/mta.yaml.hbs +14 -0
  95. package/lib/init/template/connectivity/files/package.json.hbs +17 -0
  96. package/lib/init/template/connectivity/index.js +21 -4
  97. package/lib/init/template/data/index.js +5 -1
  98. package/lib/init/template/destination/files/mta.yaml.hbs +14 -0
  99. package/lib/init/template/destination/files/package.json.hbs +17 -0
  100. package/lib/init/template/{destinations → destination}/index.js +19 -13
  101. package/lib/init/template/enterprise-messaging/files/event-mesh.json.hbs +3 -3
  102. package/lib/init/template/enterprise-messaging/files/mta.yaml.hbs +5 -5
  103. package/lib/init/template/enterprise-messaging/files/package.json.hbs +9 -9
  104. package/lib/init/template/enterprise-messaging/files/xs-security.json.hbs +19 -0
  105. package/lib/init/template/enterprise-messaging/index.js +27 -6
  106. package/lib/init/template/enterprise-messaging-shared/files/event-mesh.json.hbs +3 -3
  107. package/lib/init/template/enterprise-messaging-shared/files/mta.yaml.hbs +5 -5
  108. package/lib/init/template/enterprise-messaging-shared/files/package.json.hbs +9 -9
  109. package/lib/init/template/enterprise-messaging-shared/index.js +4 -5
  110. package/lib/init/template/extensibility/files/package.json.hbs +10 -10
  111. package/lib/init/template/extensibility/index.js +8 -9
  112. package/lib/init/template/file-based-messaging/files/package.json.hbs +9 -9
  113. package/lib/init/template/file-based-messaging/index.js +3 -4
  114. package/lib/init/template/hana/files/db/package.json +1 -1
  115. package/lib/init/template/hana/files/mta.yaml.hbs +21 -21
  116. package/lib/init/template/hana/files/package.json.hbs +16 -22
  117. package/lib/init/template/hana/files/values.yaml.hbs +1 -1
  118. package/lib/init/template/hana/index.js +5 -15
  119. package/lib/init/template/helm/files/Chart.yaml.hbs +4 -4
  120. package/lib/init/template/helm/files/values.yaml.hbs +6 -6
  121. package/lib/init/template/helm/index.js +5 -10
  122. package/lib/init/template/helm/subcharts/content-deployment/Chart.yaml +2 -0
  123. package/lib/init/template/helm/subcharts/content-deployment/templates/_helpers.tpl +37 -31
  124. package/lib/init/template/helm/subcharts/content-deployment/templates/job.yaml +13 -14
  125. package/lib/init/template/helm/subcharts/content-deployment/templates/secret.yaml +2 -2
  126. package/lib/init/template/helm/subcharts/content-deployment/templates/service-account.yaml +1 -1
  127. package/lib/init/template/helm/subcharts/content-deployment/templates/service-binding.yaml +3 -3
  128. package/lib/init/template/helm/subcharts/content-deployment/values.md +116 -116
  129. package/lib/init/template/helm/subcharts/service-instance/Chart.yaml +2 -0
  130. package/lib/init/template/helm/subcharts/service-instance/templates/_helpers.tpl +9 -9
  131. package/lib/init/template/helm/subcharts/service-instance/templates/serviceinstance.yaml +2 -2
  132. package/lib/init/template/helm/subcharts/service-instance/values.md +15 -15
  133. package/lib/init/template/helm/subcharts/web-application/Chart.yaml +2 -0
  134. package/lib/init/template/helm/subcharts/web-application/templates/NOTES.txt +15 -0
  135. package/lib/init/template/helm/subcharts/web-application/templates/_helpers.tpl +23 -23
  136. package/lib/init/template/helm/subcharts/web-application/templates/api-rule.yaml +4 -4
  137. package/lib/init/template/helm/subcharts/web-application/templates/deployment.yaml +17 -17
  138. package/lib/init/template/helm/subcharts/web-application/templates/network-policy.yaml +24 -3
  139. package/lib/init/template/helm/subcharts/web-application/templates/pod-disruption-budget.yaml +3 -3
  140. package/lib/init/template/helm/subcharts/web-application/templates/secret.yaml +2 -2
  141. package/lib/init/template/helm/subcharts/web-application/templates/service-account.yaml +1 -1
  142. package/lib/init/template/helm/subcharts/web-application/templates/service-binding.yaml +3 -3
  143. package/lib/init/template/helm/subcharts/web-application/templates/service.yaml +3 -3
  144. package/lib/init/template/helm/subcharts/web-application/values.md +141 -123
  145. package/lib/init/template/helm/subcharts/web-application/values.schema.json +7 -0
  146. package/lib/init/template/helm/subcharts/web-application/values.yaml +1 -0
  147. package/lib/init/template/html5-repo/index.js +4 -5
  148. package/lib/init/template/java/index.js +5 -5
  149. package/lib/init/template/kibana-logging/files/mta.yaml.hbs +5 -5
  150. package/lib/init/template/kibana-logging/files/package.json.hbs +9 -9
  151. package/lib/init/template/kibana-logging/index.js +3 -4
  152. package/lib/init/template/lint/index.js +3 -3
  153. package/lib/init/template/mta/files/mta.yaml.hbs +14 -14
  154. package/lib/init/template/mta/files/package.json +5 -0
  155. package/lib/init/template/mta/index.js +12 -13
  156. package/lib/init/template/mtx/index.js +2 -2
  157. package/lib/init/template/multitenancy/files/mta.yaml.hbs +29 -27
  158. package/lib/init/template/multitenancy/files/package.json.hbs +17 -14
  159. package/lib/init/template/multitenancy/files/package.sidecar.json.hbs +7 -7
  160. package/lib/init/template/multitenancy/files/values.yaml.hbs +19 -19
  161. package/lib/init/template/multitenancy/index.js +14 -16
  162. package/lib/init/template/nodejs/files/package.json.hbs +1 -1
  163. package/lib/init/template/nodejs/index.js +5 -8
  164. package/lib/init/template/redis-messaging/files/mta.yaml.hbs +5 -5
  165. package/lib/init/template/redis-messaging/files/package.json.hbs +9 -9
  166. package/lib/init/template/redis-messaging/index.js +4 -5
  167. package/lib/init/template/sample/files/app/_i18n/i18n.properties +43 -0
  168. package/lib/init/template/sample/files/app/_i18n/i18n_de.properties +14 -0
  169. package/lib/init/template/sample/files/app/admin-books/fiori-service.cds +114 -0
  170. package/lib/init/template/sample/files/app/admin-books/webapp/Component.js +8 -0
  171. package/lib/init/template/sample/files/app/admin-books/webapp/i18n/i18n.properties +11 -0
  172. package/lib/init/template/sample/files/app/admin-books/webapp/manifest.json +129 -0
  173. package/lib/init/template/sample/files/app/appconfig/fioriSandboxConfig.json +57 -0
  174. package/lib/init/template/sample/files/app/common.cds +263 -0
  175. package/lib/init/template/sample/files/app/index.html +30 -0
  176. package/lib/init/template/sample/files/app/services.cds +5 -0
  177. package/lib/init/template/sample/files/db/data/sap.capire.bookshop-Authors.csv +5 -0
  178. package/lib/init/template/sample/files/db/data/sap.capire.bookshop-Books.csv +6 -0
  179. package/lib/init/template/sample/files/db/data/sap.capire.bookshop-Books_texts.csv +5 -0
  180. package/lib/init/template/sample/files/db/data/sap.capire.bookshop-Genres.csv +16 -0
  181. package/lib/init/template/sample/files/db/schema.cds +31 -0
  182. package/lib/init/template/sample/files/nodejs/admin-service.js +12 -0
  183. package/lib/init/template/sample/files/nodejs/cat-service.js +26 -0
  184. package/lib/init/template/sample/files/srv/admin-service.cds +5 -0
  185. package/lib/init/template/sample/files/srv/cat-service.cds +16 -0
  186. package/lib/init/template/sample/index.js +24 -0
  187. package/lib/init/template/sample-tiny/index.js +39 -0
  188. package/lib/init/template/samples/index.js +5 -56
  189. package/lib/init/template/sqlite/files/package.json.hbs +13 -13
  190. package/lib/init/template/sqlite/index.js +2 -2
  191. package/lib/init/template/templateBase.js +24 -1
  192. package/lib/init/template/toggles/files/package.json.hbs +10 -10
  193. package/lib/init/template/toggles/index.js +3 -3
  194. package/lib/init/template/typer/files/gitignore +1 -0
  195. package/lib/init/template/typer/files/package.json +8 -0
  196. package/lib/init/template/typer/files/xsconfig.json +9 -0
  197. package/lib/init/template/typer/index.js +36 -0
  198. package/lib/init/template/xsuaa/files/mta.yaml.hbs +12 -12
  199. package/lib/init/template/xsuaa/files/package.json.hbs +13 -13
  200. package/lib/init/template/xsuaa/files/values.yaml.hbs +8 -8
  201. package/lib/init/template/xsuaa/index.js +8 -19
  202. package/lib/init/util/merge.js +73 -59
  203. package/lib/init/util/mvn.js +21 -17
  204. package/lib/init/util/projectReader.js +49 -87
  205. package/lib/init/util/xml.js +14 -23
  206. package/lib/util/cfUtil.js +366 -0
  207. package/lib/util/command.js +3 -3
  208. package/lib/util/gitUtil.js +55 -0
  209. package/lib/util/version.js +27 -0
  210. package/npm-shrinkwrap.json +339 -277
  211. package/package.json +6 -6
  212. package/CHANGELOG.md +0 -1453
  213. package/bin/build/all.js +0 -88
  214. package/bin/build/index.js +0 -82
  215. package/lib/compile/index.js +0 -14
  216. /package/lib/init/template/{samples → sample-tiny}/files/nodejs/db/data/my.bookshop-Books.csv +0 -0
  217. /package/lib/init/template/{samples → sample-tiny}/files/nodejs/db/data-model.cds +0 -0
  218. /package/lib/init/template/{samples → sample-tiny}/files/nodejs/srv/cat-service.cds.hbs +0 -0
@@ -0,0 +1,137 @@
1
+
2
+ {
3
+ "file_suffixes": {
4
+ "csv": {
5
+ "plugin_name": "com.sap.hana.di.tabledata.source"
6
+ },
7
+ "hdbafllangprocedure": {
8
+ "plugin_name": "com.sap.hana.di.afllangprocedure"
9
+ },
10
+ "hdbanalyticprivilege": {
11
+ "plugin_name": "com.sap.hana.di.analyticprivilege"
12
+ },
13
+ "hdbcalculationview": {
14
+ "plugin_name": "com.sap.hana.di.calculationview"
15
+ },
16
+ "hdbcollection": {
17
+ "plugin_name": "com.sap.hana.di.collection"
18
+ },
19
+ "hdbconstraint": {
20
+ "plugin_name": "com.sap.hana.di.constraint"
21
+ },
22
+ "hdbdropcreatetable": {
23
+ "plugin_name": "com.sap.hana.di.dropcreatetable"
24
+ },
25
+ "hdbflowgraph": {
26
+ "plugin_name": "com.sap.hana.di.flowgraph"
27
+ },
28
+ "hdbfunction": {
29
+ "plugin_name": "com.sap.hana.di.function"
30
+ },
31
+ "hdbgraphworkspace": {
32
+ "plugin_name": "com.sap.hana.di.graphworkspace"
33
+ },
34
+ "hdbhadoopmrjob": {
35
+ "plugin_name": "com.sap.hana.di.virtualfunctionpackage.hadoop"
36
+ },
37
+ "hdbindex": {
38
+ "plugin_name": "com.sap.hana.di.index"
39
+ },
40
+ "hdblibrary": {
41
+ "plugin_name": "com.sap.hana.di.library"
42
+ },
43
+ "hdbmigrationtable": {
44
+ "plugin_name": "com.sap.hana.di.table.migration"
45
+ },
46
+ "hdbprocedure": {
47
+ "plugin_name": "com.sap.hana.di.procedure"
48
+ },
49
+ "hdbprojectionview": {
50
+ "plugin_name": "com.sap.hana.di.projectionview"
51
+ },
52
+ "hdbprojectionviewconfig": {
53
+ "plugin_name": "com.sap.hana.di.projectionview.config"
54
+ },
55
+ "hdbreptask": {
56
+ "plugin_name": "com.sap.hana.di.reptask"
57
+ },
58
+ "hdbresultcache": {
59
+ "plugin_name": "com.sap.hana.di.resultcache"
60
+ },
61
+ "hdbrole": {
62
+ "plugin_name": "com.sap.hana.di.role"
63
+ },
64
+ "hdbroleconfig": {
65
+ "plugin_name": "com.sap.hana.di.role.config"
66
+ },
67
+ "hdbsearchruleset": {
68
+ "plugin_name": "com.sap.hana.di.searchruleset"
69
+ },
70
+ "hdbsequence": {
71
+ "plugin_name": "com.sap.hana.di.sequence"
72
+ },
73
+ "hdbstatistics": {
74
+ "plugin_name": "com.sap.hana.di.statistics"
75
+ },
76
+ "hdbstructuredprivilege": {
77
+ "plugin_name": "com.sap.hana.di.structuredprivilege"
78
+ },
79
+ "hdbsynonym": {
80
+ "plugin_name": "com.sap.hana.di.synonym"
81
+ },
82
+ "hdbsynonymconfig": {
83
+ "plugin_name": "com.sap.hana.di.synonym.config"
84
+ },
85
+ "hdbsystemversioning": {
86
+ "plugin_name": "com.sap.hana.di.systemversioning"
87
+ },
88
+ "hdbtable": {
89
+ "plugin_name": "com.sap.hana.di.table"
90
+ },
91
+ "hdbtabledata": {
92
+ "plugin_name": "com.sap.hana.di.tabledata"
93
+ },
94
+ "hdbtabletype": {
95
+ "plugin_name": "com.sap.hana.di.tabletype"
96
+ },
97
+ "hdbtrigger": {
98
+ "plugin_name": "com.sap.hana.di.trigger"
99
+ },
100
+ "hdbview": {
101
+ "plugin_name": "com.sap.hana.di.view"
102
+ },
103
+ "hdbvirtualfunction": {
104
+ "plugin_name": "com.sap.hana.di.virtualfunction"
105
+ },
106
+ "hdbvirtualfunctionconfig": {
107
+ "plugin_name": "com.sap.hana.di.virtualfunction.config"
108
+ },
109
+ "hdbvirtualpackagehadoop": {
110
+ "plugin_name": "com.sap.hana.di.virtualpackage.hadoop"
111
+ },
112
+ "hdbvirtualpackagesparksql": {
113
+ "plugin_name": "com.sap.hana.di.virtualpackage.sparksql"
114
+ },
115
+ "hdbvirtualprocedure": {
116
+ "plugin_name": "com.sap.hana.di.virtualprocedure"
117
+ },
118
+ "hdbvirtualprocedureconfig": {
119
+ "plugin_name": "com.sap.hana.di.virtualprocedure.config"
120
+ },
121
+ "hdbvirtualtable": {
122
+ "plugin_name": "com.sap.hana.di.virtualtable"
123
+ },
124
+ "hdbvirtualtableconfig": {
125
+ "plugin_name": "com.sap.hana.di.virtualtable.config"
126
+ },
127
+ "properties": {
128
+ "plugin_name": "com.sap.hana.di.tabledata.properties"
129
+ },
130
+ "tags": {
131
+ "plugin_name": "com.sap.hana.di.tabledata.properties"
132
+ },
133
+ "txt": {
134
+ "plugin_name": "com.sap.hana.di.copyonly"
135
+ }
136
+ }
137
+ }
@@ -0,0 +1,4 @@
1
+ {
2
+ "name": "",
3
+ "subfolder": "ignore"
4
+ }
@@ -0,0 +1,12 @@
1
+ {
2
+ "name": "deploy",
3
+ "dependencies": {
4
+ "@sap/hdi-deploy": "^4"
5
+ },
6
+ "engines": {
7
+ "node": "^14 || ^16 || ^18"
8
+ },
9
+ "scripts": {
10
+ "start": "node node_modules/@sap/hdi-deploy/deploy.js"
11
+ }
12
+ }
@@ -0,0 +1,5 @@
1
+ [
2
+ "src/gen/**/*.hdbview",
3
+ "src/gen/**/*.hdbindex",
4
+ "src/gen/**/*.hdbconstraint"
5
+ ]
@@ -0,0 +1,93 @@
1
+ const fs = require('fs')
2
+ const path = require('path')
3
+ const cds = require('../../../cds')
4
+ const BuildTaskHandlerEdmx = require('../buildTaskHandlerEdmx')
5
+ const { OUTPUT_MODE, OUTPUT_MODE_RESULT, FILE_EXT_CDS, CONTENT_LANGUAGE_BUNDLES, CONTENT_DEFAULT_CSN, DEFAULT_CSN_FILE_NAME } = require('../../constants')
6
+ const DEFAULT_COMPILE_DEST_FOLDER = path.normalize('src/main/resources/edmx')
7
+
8
+ class JavaModuleBuilder extends BuildTaskHandlerEdmx {
9
+ init() {
10
+ super.init()
11
+ this.task.options.compileDest = path.resolve(this.task.dest, this.task.options.compileDest || DEFAULT_COMPILE_DEST_FOLDER)
12
+ }
13
+
14
+ async build() {
15
+ const { src, dest } = this.task
16
+
17
+ const odataOptions = {
18
+ version: cds.env.odata?.version
19
+ }
20
+
21
+ const model = await this.model()
22
+ if (!model) {
23
+ return
24
+ }
25
+
26
+ const odata = await this._compileForOdata(model, this.task.options.compileDest, odataOptions)
27
+ await this.compileToEdmx(odata, this.task.options.compileDest, odataOptions)
28
+
29
+ if (this.hasBuildOption(CONTENT_LANGUAGE_BUNDLES, true)) {
30
+ // collect and write language bundles into single i18n.json file
31
+ const i18nFolder = cds.env.i18n.folders?.[0] || 'i18n'
32
+ const i18n = await this.collectLanguageBundles(model, path.join(this.task.dest, i18nFolder))
33
+ if (i18n && this.hasBuildOption(OUTPUT_MODE, OUTPUT_MODE_RESULT)) {
34
+ this._result.languageBundles = i18n.bundles
35
+ }
36
+ }
37
+ if (this.isStagingBuild() && this.hasBuildOption(OUTPUT_MODE, OUTPUT_MODE_RESULT)) {
38
+ await this._copyNativeContent(src, dest)
39
+ }
40
+ return this._result
41
+ }
42
+
43
+ async clean() {
44
+ if (this.isStagingBuild()) {
45
+ return super.clean()
46
+ }
47
+ this.logger._debug && this.logger.debug(`Deleting build target folder ${this.task.options.compileDest}`)
48
+ await fs.promises.rm(this.task.options.compileDest, { force: true, recursive: true })
49
+ }
50
+
51
+ async _copyNativeContent(src, dest) {
52
+ return super.copyNativeContent(src, dest, (entry) => {
53
+ if (fs.statSync(entry).isDirectory()) {
54
+ return true // using common filter for folders
55
+ } else {
56
+ const extname = path.extname(entry)
57
+ return extname !== FILE_EXT_CDS
58
+ }
59
+ })
60
+ }
61
+
62
+ async _compileForOdata(model, csnDest, compileOptions) {
63
+ // csn for service providers
64
+ const m = cds.compile.for.java(model, {
65
+ ...this._options4odata(),
66
+ ...compileOptions
67
+ })
68
+ const csnFile = path.join(csnDest, DEFAULT_CSN_FILE_NAME)
69
+ let csnModel
70
+ // adding csn to build result containing @source and _where persisted properties
71
+ if (this.hasBuildOption(CONTENT_DEFAULT_CSN, true)) { //default true or undefined
72
+ const csnStr = await this.compileToJson(model, csnFile)
73
+ csnModel = JSON.parse(csnStr)
74
+ csnModel.meta = model.meta
75
+ } else {
76
+ const csnStr = await this.compileToJson(m, csnFile)
77
+ csnModel = JSON.parse(csnStr)
78
+ csnModel.meta = m.meta
79
+ }
80
+ if (this.hasBuildOption(OUTPUT_MODE, OUTPUT_MODE_RESULT)) {
81
+ this._result.csn = csnModel
82
+ }
83
+
84
+ return m
85
+ }
86
+
87
+ _isCompilerV1() {
88
+ const version = cds.compiler.version()
89
+ const match = version.match(/(\d+)\.?(\d*)\.?(\d*)/)
90
+ return match && match[1] === 1
91
+ }
92
+ }
93
+ module.exports = JavaModuleBuilder
@@ -0,0 +1 @@
1
+ module.exports = require('../java')
@@ -0,0 +1,37 @@
1
+ /* eslint-disable no-empty */
2
+ const fs = require('fs')
3
+ const path = require('path')
4
+ const cds = require('../../../cds')
5
+ const BuildTaskHandlerEdmx = require('../buildTaskHandlerEdmx')
6
+ const ResourcesTarProvider = require('./resourcesTarBuilder')
7
+ const { FOLDER_GEN } = require('../../constants')
8
+
9
+ class MtxModuleBuilder extends BuildTaskHandlerEdmx {
10
+ get priority() {
11
+ // should be scheduled after 'hana' build tasks are finished
12
+ return BuildTaskHandlerEdmx.PRIORITY_MIN_VALUE
13
+ }
14
+ init() {
15
+ super.init()
16
+ }
17
+
18
+ async build() {
19
+ // Non-sidecar scenario: model-provider is implemented by the Nodejs app itself (default for Nodejs).
20
+ // Only create resources TAR, compiled CSN(s) are created by the Nodejs app build task.
21
+ const dest = cds.env.build.target !== "." ? this.task.dest : path.join(this.task.dest, FOLDER_GEN)
22
+ const model = await this.model()
23
+ if (!model) {
24
+ return
25
+ }
26
+ return new ResourcesTarProvider(this).createTar(dest, model)
27
+ }
28
+
29
+ async clean() {
30
+ // staging build content is deleted by BuildTaskEngine
31
+ if (cds.env.build.target === '.') {
32
+ // remove 'gen' folder
33
+ return fs.promises.rm(path.join(this.task.dest, FOLDER_GEN), { force: true, recursive: true })
34
+ }
35
+ }
36
+ }
37
+ module.exports = MtxModuleBuilder
@@ -0,0 +1,94 @@
1
+ const path = require('path')
2
+ const cds = require('../../../cds')
3
+ const BuildTaskHandlerInternal = require('../buildTaskHandlerInternal')
4
+
5
+ const { BUILD_TASK_HANA } = require('../../constants')
6
+ const fs = require('fs')
7
+ const { WARNING } = BuildTaskHandlerInternal
8
+ const DEFAULT_TAR_NAME = "resources.tgz"
9
+
10
+ class ResourcesTarBuilder {
11
+ constructor(handler) {
12
+ this._handler = handler
13
+ }
14
+
15
+ get handler() { return this._handler }
16
+
17
+ async createTar(dest, model) {
18
+ const { root, resources } = await this._getResources(model)
19
+ if (resources.length === 0) {
20
+ // packTarArchive fails otherwise
21
+ this.handler.pushMessage("No deployment resources found - skip resources.tgz", WARNING)
22
+ return
23
+ }
24
+ await this.writeTarFile(path.join(dest, DEFAULT_TAR_NAME), root, resources)
25
+ }
26
+
27
+ /**
28
+ * Creates a TAR file at the given absolute tarPath. An optional resources list holds the files and folders
29
+ * that will be added to the TAR. Paths are relative to the passed root directory. If omitted, the entire
30
+ * root directory contents will be added.
31
+ * @param {*} tarFile Absolute TAR file name.
32
+ * @param {*} root The root directory the passed resources are relative to.
33
+ * @param {*} resources Optional list of absolute or relative resource paths - relative to the given root directory.
34
+ * If omitted all resources contained in the root directory are added to the TAR file.
35
+ */
36
+ async writeTarFile(tarFile, root, resources) {
37
+ const { tar } = require('../../../../lib').utils
38
+ await tar.czfd(tarFile, root, resources)
39
+ this.handler.pushFile(tarFile)
40
+ }
41
+
42
+ async _getResources(model) {
43
+ // distinguish HANA and SQLITE deployment
44
+ let root = await this._getHanaTenantDbDest()
45
+ let resources
46
+ if (root) {
47
+ resources = this._getHanaResources(root)
48
+ } else {
49
+ root = cds.root
50
+ resources = await this._getSqliteResources(model)
51
+ }
52
+ return { root, resources }
53
+ }
54
+
55
+ /**
56
+ * Reads a list of files and folders required for HANA deployment.
57
+ * This is a subset of all files contained in the directory.
58
+ * - 'db/src', 'db/cfg', 'db/undeploy.json'...
59
+ * See '../../../../lib.deploy'
60
+ * Note: the hana build task has already been executed
61
+ * @param {string} root
62
+ * @returns an array containing all resources
63
+ */
64
+ _getHanaResources(root) {
65
+ return ['src', 'cfg', 'undeploy.json', '.hdiignore'].reduce((acc, res) => {
66
+ const resPath = path.join(root, res)
67
+ if (fs.existsSync(resPath)) {
68
+ acc.push(resPath)
69
+ }
70
+ return acc
71
+ }, [])
72
+ }
73
+
74
+ /**
75
+ * Reads all resources for Sqlite deployment - see '../../../../lib.deploy'
76
+ *
77
+ * @param {object} model
78
+ * @returns
79
+ */
80
+ async _getSqliteResources(model) {
81
+ const { resources } = cds.deploy
82
+ return Object.keys(await resources(model))
83
+ }
84
+
85
+ async _getHanaTenantDbDest() {
86
+ let hanaTask = this.handler.context.tasks.find(task => task.for === BUILD_TASK_HANA)
87
+ if (!hanaTask) {
88
+ this.handler.pushMessage(`Found SQLite database configuration. Ensure that productive cloud deployments requiring SAP HANA database are built with 'production' profile.`, WARNING)
89
+ return null
90
+ }
91
+ return hanaTask.dest
92
+ }
93
+ }
94
+ module.exports = ResourcesTarBuilder
@@ -0,0 +1,131 @@
1
+ const path = require('path')
2
+ const fs = require('fs')
3
+ const cds = require('../../../cds')
4
+
5
+ const BuildTaskHandlerInternal = require('../buildTaskHandlerInternal')
6
+ const { FOLDER_GEN, EXTENSION_POINT_VALIDATION } = require('../../constants')
7
+ const ResourcesTarBuilder = require('../mtx/resourcesTarBuilder')
8
+ const { BuildError, BuildMessage } = require('../../util')
9
+
10
+ class MtxExtensionModuleBuilder extends BuildTaskHandlerInternal {
11
+ init() {
12
+ super.init()
13
+ if (cds.env.build.target === '.') {
14
+ this.task.dest = path.join(this.task.dest, FOLDER_GEN)
15
+ }
16
+ }
17
+
18
+ async build() {
19
+ const { src, dest } = this.task
20
+ const destExt = path.join(dest, 'ext')
21
+ // check existence of appPackage folder only
22
+ // REVISIT: cds.resolve will fail as no index.csn file exists in this folder for the extension migration use case
23
+ // a compilation error is thrown anyhow if any base model refs cannot be resolved
24
+ const appPackageFolder = this._getAppPackageFolder()
25
+ if (!fs.existsSync(path.join(src, appPackageFolder))) {
26
+ throw new BuildError(`The SaaS application base model '${appPackageFolder}' is missing. Have you run the 'cds pull' command?`)
27
+ }
28
+
29
+ // full compile of the extension using base model - ensuring consistency
30
+ const model = await this.model()
31
+
32
+ if (model) {
33
+ // extension CSN using parsed format
34
+ const options = { ...this.options(), flavor: 'parsed' }
35
+ const extModel = await cds.load(this._resolveExtensionFiles(model), options)
36
+ if (extModel.requires) {
37
+ extModel.requires.length = 0
38
+ }
39
+
40
+ if (!this.hasBuildOption(EXTENSION_POINT_VALIDATION, false)) {
41
+ this._lintExtModel(extModel, model) // throws error in case of linting errors
42
+ }
43
+
44
+ await this.compileToJson(extModel, path.join(destExt, 'extension.csn'))
45
+
46
+ await this.collectLanguageBundles(extModel, path.join(destExt, 'i18n'))
47
+
48
+ const files = Object.keys(await cds.deploy.resources(model))
49
+ if (files.length > 0) {
50
+ const dataDest = path.join(destExt, 'data')
51
+ await Promise.all(
52
+ files
53
+ .filter(file => /\.csv$/.test(file))
54
+ .map(csv => {
55
+ return this.copy(csv).to(path.join(dataDest, path.basename(csv)))
56
+ })
57
+ )
58
+ }
59
+ }
60
+
61
+ const packageJson = path.join(src, 'package.json')
62
+ if (!fs.existsSync(packageJson)) {
63
+ throw new BuildError(`package.json file not found in ${src}`)
64
+ }
65
+ await this.copy(packageJson).to(path.join(destExt, 'package.json'))
66
+
67
+ // copy handlers
68
+ const folders = [path.join(src, cds.env.folders.srv, 'handlers')]
69
+ await this.copyNativeContent(src, destExt, res => {
70
+ if (fs.statSync(res).isDirectory()) {
71
+ return folders.some(folder => folder.startsWith(res))
72
+ }
73
+ if (folders.includes(path.dirname(res)) && /\.js$/.test(res)) {
74
+ return true
75
+ }
76
+ })
77
+
78
+ // add all resources contained in 'gen/ext' folder
79
+ await new ResourcesTarBuilder(this).writeTarFile(path.join(this.task.dest, 'extension.tgz'), destExt)
80
+ }
81
+
82
+ _resolveExtensionFiles(model) {
83
+ const node_modules = path.join(this.task.src, 'node_modules')
84
+ const paths = model['$sources'].reduce((acc, file) => {
85
+ if (file.startsWith(this.task.src) && !file.startsWith(node_modules)) {
86
+ acc.push(file)
87
+ }
88
+ return acc
89
+ }, [])
90
+
91
+ return paths
92
+ }
93
+
94
+ _lintExtModel(extModel, model) {
95
+ const linter = this._linter()
96
+ if (!linter) {
97
+ return
98
+ }
99
+ const env = cds.env.for('cds', path.join(this.task.src, this._getAppPackageFolder()))
100
+ this.logger._debug && this.logger.debug(`Saas extension point restrictions:\n${env.requires?.['cds.xt.ExtensibilityService']}`)
101
+
102
+ const messages = linter.lint(extModel, model, env)
103
+ if (messages.length) {
104
+ // REVISIT: lint messages can be passed as is with cds-mtxs version >= 1.7
105
+ throw new BuildError('SaaS extension point restrictions violated. Check the concrete restrictions defined by the SaaS app provider.',
106
+ messages.map(f => new BuildMessage(f.message, f.severity, f.location || f.element?.$location)))
107
+ }
108
+ }
109
+
110
+ _linter() {
111
+ let linter
112
+ try {
113
+ // Make sure cds-mtxs APIs are loaded
114
+ linter = require('@sap/cds-mtxs').xt?.linter
115
+ if (!linter) {
116
+ this.pushMessage('MTXS linter cannot be loaded. Update of @sap/cds-dk and @sap/cds-mtxs modules required? Skipping extension model lint step.')
117
+ return null // too old mtxs
118
+ }
119
+ } catch (e) {
120
+ if (e.code !== 'MODULE_NOT_FOUND') throw e
121
+ this.pushMessage('MTXS linter cannot be loaded, @sap/cds-mtxs not installed. Skipping extension model lint step.')
122
+ }
123
+ return linter
124
+ }
125
+
126
+ _getAppPackageFolder() {
127
+ return path.join('node_modules', cds.env.extends || '_base');
128
+ }
129
+ }
130
+
131
+ module.exports = MtxExtensionModuleBuilder
@@ -0,0 +1,138 @@
1
+ const path = require('path')
2
+ const cds = require('../../../cds')
3
+ const fs = require('fs')
4
+ const { FOLDER_GEN, DEFAULT_CSN_FILE_NAME } = require('../../constants')
5
+ const NodeCfModuleBuilder = require('../nodejs')
6
+ const ResourcesTarProvider = require('../mtx/resourcesTarBuilder')
7
+ const { WARNING, ERROR } = NodeCfModuleBuilder
8
+ const { relativePaths, BuildError, resolveRequiredSapModels } = require('../../util')
9
+
10
+ const DEFAULT_MAIN_FOLDER = "_main"
11
+
12
+ class MtxSidecarModuleBuilder extends NodeCfModuleBuilder {
13
+ get priority() {
14
+ // should be scheduled after 'hana' build tasks are finished
15
+ return NodeCfModuleBuilder.PRIORITY_MIN_VALUE
16
+ }
17
+ init() {
18
+ super.init()
19
+ if (cds.env.build.target === '.') {
20
+ this.task.dest = path.join(this.task.dest, FOLDER_GEN)
21
+ }
22
+ }
23
+
24
+ /**
25
+ * Builds the mtx sidecar app consisting of:
26
+ * - nodejs app model defined by the required sidecar services
27
+ * - main app model defined by the build task's model options including feature models and resources TAR
28
+ *
29
+ * build.target=".": 'dest' -> 'model-provider/gen'
30
+ * build.target="gen": 'dest' -> 'gen/model-provider'
31
+ */
32
+ async build() {
33
+ // nodejs app parts have to be built using sidecar env
34
+ const sidecarEnv = cds.env.for("cds", this.task.src)
35
+ // build main application
36
+ await this._buildMainApp(sidecarEnv)
37
+ // build node application
38
+ await this._buildNodeApp(sidecarEnv)
39
+ }
40
+
41
+ /**
42
+ * Builds the mtx sidecar nodejs app parts.
43
+ * @param {object} sidecarEnv cds env based on the sidecar dir
44
+ */
45
+ async _buildNodeApp(sidecarEnv) {
46
+ const destSidecar = this.task.dest
47
+ const destSidecarSrc = path.join(destSidecar, cds.env.folders.srv)
48
+ const i18nFolder = cds.env.i18n.folders?.[0] || 'i18n'
49
+ const model = this._compileSidecarSync(sidecarEnv)
50
+ await this.compileToJson(model, path.join(destSidecarSrc, DEFAULT_CSN_FILE_NAME))
51
+
52
+ await this.collectLanguageBundles(model, path.join(destSidecarSrc, i18nFolder))
53
+ await this.copyProjectRootContent(this.task.src, destSidecar)
54
+ }
55
+
56
+ /**
57
+ * Builds the main app parts containing base model CSN with feature CSNs and resources TAR.
58
+ * @param {object} sidecarEnv cds env based on the sidecar dir
59
+ */
60
+ async _buildMainApp(sidecarEnv) {
61
+ let main = sidecarEnv.requires['cds.xt.ModelProviderService']?.root
62
+ if (!main) {
63
+ throw new BuildError(`Invalid MTX sidecar configuration. Make sure that the profile 'mtx-sidecar' is configured and an up-to-date version of @sap/cds-mtxs is installed.`)
64
+ }
65
+ const profiles = cds.env.profiles || []
66
+
67
+ if (!profiles.includes("production") && !profiles.includes("prod")) {
68
+ main = DEFAULT_MAIN_FOLDER
69
+ // root should represent the production use case and not development
70
+ this.pushMessage(`MTX sidecar build results are created in folder '${main}'. Enable 'production' or 'prod' profile if the folder is configured differently.`, WARNING)
71
+ }
72
+ const destRoot = this.task.dest
73
+ const destMain = path.join(destRoot, main)
74
+ const destMainSrv = path.join(destMain, cds.env.folders.srv)
75
+ const csn = await this.model()
76
+ if (!csn) {
77
+ return
78
+ }
79
+ const { dictionary, sources } = await this.compileAll(csn, destMainSrv, destMain)
80
+ await this.collectAllLanguageBundles(dictionary, sources, destMainSrv, destMain)
81
+
82
+ // create resources TAR
83
+ // resources are determined based on available database build task, SQLite as fallback
84
+ await new ResourcesTarProvider(this).createTar(destMain, csn)
85
+
86
+ // copy package.json and .cdsrc.json from project root
87
+ await this._copyMainConfigFiles(cds.root, destMain)
88
+ }
89
+
90
+ /**
91
+ * Synchronous compilation using the sidecar context.
92
+ * @param {object} sidecarEnv cds env based on the sidecar dir
93
+ * @returns the compiled mtx sidecar CSN
94
+ */
95
+ _compileSidecarSync(sidecarEnv) {
96
+ const env = cds.env
97
+ const root = cds.root
98
+ try {
99
+ cds.root = this.task.src
100
+ cds.env = sidecarEnv
101
+ const modelPaths = cds.resolve('*', false)
102
+ const modelFilePaths = cds.resolve(modelPaths)
103
+
104
+ if (!modelFilePaths || modelFilePaths.length === 0) {
105
+ throw new BuildError("No CDS models found in MTX sidecar. Make sure up-to-date versions of the required npm modules are installed.")
106
+ }
107
+ this._logger._debug && this._logger.debug(`sidecar model: ${relativePaths(cds.root, modelFilePaths).join(", ")}`)
108
+
109
+ // check whether all models belonging to the @sap namespace can be resolved
110
+ const unresolved = resolveRequiredSapModels(modelPaths)
111
+ if (unresolved.length > 0) {
112
+ // log error, but don't fail
113
+ this.pushMessage(`CDS models [${unresolved.join(', ')}] required by MTX sidecar cannot be resolved. Make sure up-to-date versions of the missing npm modules are installed.`, ERROR)
114
+ }
115
+
116
+ // synchronous compilation
117
+ return cds.load(modelFilePaths, { sync: true, ...this.options() })
118
+ } finally {
119
+ // restore project scope
120
+ cds.root = root
121
+ cds.env = env
122
+ }
123
+ }
124
+
125
+ async _copyMainConfigFiles(src, dest) {
126
+ const packageJson = path.join(src, 'package.json')
127
+ const cdsrcJson = path.join(src, '.cdsrc.json')
128
+ const promises = []
129
+ if (fs.existsSync(packageJson)) {
130
+ promises.push(this.copy(packageJson).to(path.join(dest, 'package.json')))
131
+ }
132
+ if (fs.existsSync(cdsrcJson)) {
133
+ promises.push(this.copy(cdsrcJson).to(path.join(dest, '.cdsrc.json')))
134
+ }
135
+ return promises
136
+ }
137
+ }
138
+ module.exports = MtxSidecarModuleBuilder
@@ -0,0 +1 @@
1
+ module.exports = require('../nodejs')