@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
@@ -1,4 +1,4 @@
1
- const { typeRegex } = require('./utils');
1
+ const { getRegExpGroups } = require('./utils');
2
2
  const messages = require("../message").getMessages();
3
3
 
4
4
  module.exports = class ParserContext {
@@ -6,9 +6,41 @@ module.exports = class ParserContext {
6
6
  * @constructor
7
7
  */
8
8
  constructor(content) {
9
+ this.topics = this.getTopics(content);
9
10
  this.services = this.getServicesFromContent(content);
10
11
  }
11
12
 
13
+ getTopicName(channelName) {
14
+ return channelName.startsWith('ce/') ? channelName.substring(3) : channelName;
15
+ }
16
+
17
+ getEventName(messageRefString) {
18
+ const lastSlashIndex = messageRefString.lastIndexOf('/');
19
+ return lastSlashIndex == -1 ? '' : messageRefString.substring(lastSlashIndex + 1);
20
+ }
21
+
22
+ /**
23
+ * Return an obect with topic annotations for messages
24
+ */
25
+ getTopics(content) {
26
+ const topics = {};
27
+
28
+ Object.entries(content.channels).forEach(([key, value]) => {
29
+ const topic = this.getTopicName(key);
30
+ if (value.subscribe && value.subscribe.message && value.subscribe.message.$ref) {
31
+ const event = this.getEventName(value.subscribe.message.$ref);
32
+ topics[event] = topic;
33
+ }
34
+
35
+ if (value.publish && value.publish.message && value.publish.message.$ref) {
36
+ const event = this.getEventName(value.publish.message.$ref);
37
+ topics[event] = topic;
38
+ }
39
+ });
40
+
41
+ return topics;
42
+ }
43
+
12
44
  /**
13
45
  * Returns services from the asyncapi json object along with the events and annotations.
14
46
  * @returns an object with all the services.
@@ -18,23 +50,31 @@ module.exports = class ParserContext {
18
50
  const serviceAnnotations = this.getServiceAnnotations(content);
19
51
 
20
52
  Object.entries(content.components.messages).forEach(([key, value]) => {
21
- // uses regex to break event name in different components
22
- const regexGroups = typeRegex.exec(key);
23
- if (regexGroups == null) {
24
- throw new Error(messages.INVALID_MESSAGE_NAME);
53
+ let eventName;
54
+ // Message name should be used to capture the event name
55
+ if (value.name) {
56
+ eventName = value.name;
57
+ } else {
58
+ throw new Error(messages.INVALID_ASYNCAPI_FILE);
25
59
  }
26
-
27
- const service = regexGroups[1] + "." + regexGroups[2];
28
- const event = regexGroups[0];
60
+ // uses regex to break event name in different components
61
+ const regExpGroups = getRegExpGroups(eventName);
62
+ const service = regExpGroups[1] + "." + regExpGroups[2];
63
+ const event = regExpGroups[0];
29
64
 
30
65
  // add service to services entry if not present
31
66
  if (!(service in services)) {
32
- services[service] = { 'kind': 'service', ...serviceAnnotations, 'events': {}, 'types': {} };
67
+ services[service] = { 'kind': 'service', '@cds.external': 'true', ...serviceAnnotations, 'events': {}, 'types': {} };
33
68
  }
34
69
 
35
70
  // add event entry to service
36
71
  const eventAnnotations = this.getEventAnnotations(value);
37
72
 
73
+ // add topic annotation
74
+ if (this.topics[event]) {
75
+ eventAnnotations['@topic'] = this.topics[event];
76
+ }
77
+
38
78
  let properties = {};
39
79
  let types = {};
40
80
 
@@ -44,7 +84,7 @@ module.exports = class ParserContext {
44
84
  [properties, types] = this.getPropertiesAndTypes(event, eventSchema);
45
85
  }
46
86
  services[service].types = types;
47
- services[service].events[event] = { 'kind': 'event', ...eventAnnotations, elements: properties };
87
+ services[service].events[event] = { 'kind': 'event', '@cds.external': 'true', ...eventAnnotations, elements: properties };
48
88
  });
49
89
 
50
90
  return services;
@@ -56,14 +96,14 @@ module.exports = class ParserContext {
56
96
  */
57
97
  getServiceAnnotations(content) {
58
98
  const serviceAnnotationsMapping = {
59
- 'x-sap-stateInfo': 'StateInfo', //expected: object
60
- 'x-sap-shortText': 'ShortText' //expected: string
99
+ 'x-sap-stateInfo': 'StateInfo', // expected: object
100
+ 'x-sap-shortText': 'ShortText' // expected: string
61
101
  };
62
102
 
63
103
  const infoAnnotationsMapping = {
64
- 'title': 'Title', //expected: string
65
- 'version': 'SchemaVersion', //expected: string
66
- 'description': 'Description' //expected: string
104
+ 'title': 'Title', // expected: string
105
+ 'version': 'SchemaVersion', // expected: string
106
+ 'description': 'Description' // expected: string
67
107
  };
68
108
 
69
109
  const annotations = this.getAnnotations(content, serviceAnnotationsMapping);
@@ -86,12 +126,12 @@ module.exports = class ParserContext {
86
126
  */
87
127
  getEventAnnotations(content) {
88
128
  const eventLevelAnnotationsMapping = {
89
- 'x-sap-event-spec-version': 'EventSpecVersion', //expected: string
90
- 'x-sap-event-source': 'EventSource', //expected: string
91
- 'x-sap-event-source-parameters': 'EventSourceParams', //expected: object
92
- 'x-sap-event-characteristics': 'EventCharacteristics', //expected: object
93
- 'x-sap-stateInfo': 'EventStateInfo', //expected: object
94
- 'x-sap-event-version': 'EventSchemaVersion' //expected: string
129
+ 'x-sap-event-spec-version': 'EventSpecVersion', // expected: string
130
+ 'x-sap-event-source': 'EventSource', // expected: string
131
+ 'x-sap-event-version': 'EventSchemaVersion', // expected: string
132
+ 'x-sap-event-source-parameters': 'EventSourceParams', // expected: object
133
+ 'x-sap-event-characteristics': 'EventCharacteristics', // expected: object
134
+ 'x-sap-stateInfo': 'EventStateInfo' // expected: object
95
135
  };
96
136
 
97
137
  const annotations = this.getAnnotations(content, eventLevelAnnotationsMapping);
@@ -100,7 +140,7 @@ module.exports = class ParserContext {
100
140
  }
101
141
 
102
142
  /**
103
- * Returns validity of the annotation value. Here the parameter
143
+ * Returns validity of the annotation value. Here the parameter
104
144
  * content is the annotation name and value of the annotation.
105
145
  * @returns true/false depending on the annotation value.
106
146
  */
@@ -120,7 +160,7 @@ module.exports = class ParserContext {
120
160
  }
121
161
 
122
162
  /**
123
- * Returns annotations for an event/service. Here the parameter content
163
+ * Returns annotations for an event/service. Here the parameter content
124
164
  * is event/service content along with the corresponding mapping.
125
165
  * @returns an object with the annotations as key value pairs.
126
166
  */
@@ -131,13 +171,14 @@ module.exports = class ParserContext {
131
171
  // case: known annotation
132
172
  if (annotationsMapping[key] && this.isValidAnnotationValue(annotationsMapping[key], value)) {
133
173
  annotations['@AsyncAPI.' + annotationsMapping[key]] = value;
134
- }
174
+ }
135
175
  // case: unkown annotation
136
176
  else if (key.startsWith('x-')) {
137
177
  if (!annotations['@AsyncAPI.Extensions']) {
138
178
  annotations['@AsyncAPI.Extensions'] = {};
139
179
  }
140
- annotations['@AsyncAPI.Extensions'][key.substring(2)] = value; //removes x- from the element
180
+ // removes x- from the element
181
+ annotations['@AsyncAPI.Extensions'][key.substring(2)] = value;
141
182
  }
142
183
  }
143
184
 
@@ -217,7 +258,7 @@ module.exports = class ParserContext {
217
258
  let typeName = eventName + "." + propertyName;
218
259
  // generate object for the introduced type
219
260
  const elements = this.getTypeElements(propertyContent);
220
- types[typeName] = { 'kind': 'type', ...elements };
261
+ types[typeName] = { 'kind': 'type', '@cds.external': 'true', ...elements };
221
262
  // referring to the generated type from the property
222
263
  propertyAttributes = { 'type': typeName };
223
264
  } else {
@@ -8,11 +8,42 @@ function validateAsyncAPI(content) {
8
8
  throw new Error(messages.INVALID_ASYNCAPI_FILE);
9
9
  }
10
10
 
11
- const typeRegex = new RegExp(
12
- '^(?<namespace>(?:[a-z][a-z0-9]*)(?:[.][a-z][a-z0-9]*)+)[.](?<businessObject>[a-zA-Z0-9]+)[.](?<operation>[a-zA-Z0-9]+)([.](?<version>v(?:[0-9]|[1-9][0-9]*)))?$'
11
+ /**
12
+ * Accepted scenarios:
13
+ * * with version info : <namespace>.<businessObject>.<operation>.<version>
14
+ * * without version info : <namespace>.<businessObject>.<operation>
15
+ *
16
+ * ? Is it mandatory for <namespace> to always follow small case notation?
17
+ * ? Is it mandatory for <businessObject> to follow Camel Case or Upper Came Case notation?
18
+ *
19
+ * ToDo: Can we support `-` in operations?
20
+ */
21
+ const regExp = new RegExp(
22
+ '^(?<namespace>(?:[a-z][a-z0-9]*)(?:[.][a-z][a-z0-9]*)+)[.](?<businessObject>[a-zA-Z0-9]+)[.](?<operation>[a-zA-Z0-9]+)[.]?(?<version>v(?:[0-9]|[1-9][0-9]*))?$'
13
23
  );
14
24
 
25
+ /**
26
+ * Validates the messages' `key` with the regExp and returns the regEx groups.
27
+ * @returns regexGroups
28
+ */
29
+ function getRegExpGroups(key) {
30
+ /**
31
+ * Result format:
32
+ * index 0: key
33
+ * index 1: <namespace> value
34
+ * index 2: <businessObject> value
35
+ * index 3: <operation> value
36
+ * index 4: <version> value; undefined if <version> is optional
37
+ */
38
+ const regExpGroups = regExp.exec(key);
39
+
40
+ if (regExpGroups == null) {
41
+ throw new Error(messages.INVALID_MESSAGE_NAME);
42
+ }
43
+ return regExpGroups;
44
+ }
45
+
15
46
  module.exports = {
16
47
  validateAsyncAPI,
17
- typeRegex
48
+ getRegExpGroups
18
49
  }
@@ -6,7 +6,7 @@ let axios = require('axios');
6
6
  const messages = require("./message").getMessages();
7
7
  const cds = require('../cds');
8
8
  const { fs, path, write, mkdirp, exists, read } = cds.utils;
9
- const cdsCompiler = require('../compile').compile.to;
9
+ const cdsCompiler = require('..').compile.to;
10
10
  const md5 = require('md5');
11
11
 
12
12
  let optionsMapping = {
@@ -66,7 +66,7 @@ async function getVersion(fileInputStream){
66
66
  } else if (version === '4.0' || version === "4.01") {
67
67
  oDataVersion = 'V4';
68
68
  }
69
-
69
+
70
70
  return oDataVersion;
71
71
  }
72
72
 
@@ -135,7 +135,7 @@ async function isValidInputFile(inputFileLoc) {
135
135
  }
136
136
 
137
137
  async function _copyToSrvExternal(file, dst, cwd) {
138
- const dstDir = path.dirname(dst), srcDir = path.dirname(file)
138
+ const dstDir = path.dirname(dst), srcDir = path.dirname(file);
139
139
  if (!file.startsWith(dstDir + path.sep)) {
140
140
  await mkdirp(dstDir);
141
141
  const copyOrMove = srcDir === cwd || srcDir == process.cwd() ? fs.renameSync : fs.copyFileSync;
@@ -160,28 +160,28 @@ async function preProcess(file, options, cwd) {
160
160
  }
161
161
 
162
162
  async function processOptions(cliOptions, odataOptions) {
163
- //maps to renaming of variables
163
+ // maps to renaming of variables
164
164
  for (let [key, value] of Object.entries(optionsMapping)) {
165
165
  if (cliOptions[key]) {
166
166
  cliOptions[value] = cliOptions[key];
167
167
  delete cliOptions[key];
168
168
  }
169
169
  }
170
- //segregating cli/odata options
170
+ // segregating cli/odata options
171
171
  apiOptions.forEach(function (item) {
172
172
  odataOptions[item] = cliOptions[item];
173
173
  delete cliOptions[item];
174
174
  });
175
- //reads cli options from environment
175
+ // reads cli options from environment
176
176
  readEnvVariables(cliOptions, true);
177
-
178
-
179
177
  }
180
178
 
181
- function _getServiceName(csn) {
179
+ function _getServiceNames(csn) {
180
+ let serviceList = [];
182
181
  for (let each in csn.definitions) {
183
- if (csn.definitions[each].kind === 'service') return each;
182
+ if (csn.definitions[each].kind === 'service') serviceList.push(each);
184
183
  }
184
+ return serviceList;
185
185
  }
186
186
 
187
187
  function _validateAndComputeOutputFilePath(outputFileLoc, as, destFilePath) {
@@ -210,7 +210,7 @@ function _validateAndComputeOutputFilePath(outputFileLoc, as, destFilePath) {
210
210
  // eg., "./a.csn", "tst.cds", "./srv/external/test", "test", "c:\windows\output\test"
211
211
  return outputFileLoc;
212
212
  } else if (outputFileLoc.endsWith("/") || outputFileLoc.endsWith("\\")) {
213
- // File name not specified ("./srv/external/", "c:\windows\output\test\")
213
+ // File name not specified ("./srv/external/", "c:\windows\output\test\")
214
214
  return outputFileLoc + path.parse(destFilePath).name;
215
215
  }
216
216
  }
@@ -252,7 +252,7 @@ async function _generateChecksumValidate(dest, output, force) {
252
252
  return existingFileContent;
253
253
  }
254
254
  }
255
- /*
255
+ /**
256
256
  * 1. current and existing checksum are different.
257
257
  * 2. checksum is missing in the existing file:
258
258
  * a. existing and current file content are same.
@@ -290,7 +290,7 @@ async function _getResult(output, as, dest, force, version) {
290
290
  case undefined:
291
291
  case "csn":
292
292
  case "json":
293
- output = JSON.stringify(output, null, ' ');
293
+ output = JSON.stringify(output, null, ' ');
294
294
  break;
295
295
  default:
296
296
  break;
@@ -304,10 +304,14 @@ async function _write(result, service, cwd) {
304
304
  output = result[0];
305
305
  dest = result[1];
306
306
  await write(dest, output, "utf-8");
307
-
308
307
  extenstion = dest.substring(dest.lastIndexOf('.'));
309
308
  dest = dest.replace(extenstion, '');
310
- using = `using { ${service} as external } from './${path.relative('srv', dest).replace(/\\/g, '/')}'`;
309
+ if (service.length > 1){
310
+ using = `using { ${service.join(', ')}} from './${path.relative('srv', dest).replace(/\\/g, '/')}'`;
311
+ }
312
+ else{
313
+ using = `using { ${service} as external } from './${path.relative('srv', dest).replace(/\\/g, '/')}'`;
314
+ }
311
315
  using = require('../util/term').info(using);
312
316
  message = `[cds] - imported API to ${path.relative(cwd, dest)}
313
317
  > use it in your CDS models through the like of:
@@ -318,29 +322,35 @@ ${using}
318
322
  console.log(message);
319
323
  }
320
324
 
321
- async function _updatePackageJson(dest, service, version, cwd) {
325
+ async function _updatePackageJson(dest, services, version, cwd) {
322
326
  const package_json = path.resolve(cwd, 'package.json');
323
327
  const conf = await exists(package_json) ? require(package_json) : {};
324
328
  const requires = ['cds', 'requires'].reduce((p, n) => p[n] || (p[n] = {}), conf);
325
329
  if (version !== 'rest') {
326
330
  version = (version === "V2") ? 'odata-v2' : 'odata';
327
331
  }
328
- if (!requires[service]) {
329
- const initial_model = path.relative(cwd, dest);
330
- const model = isLinux() ? initial_model.replace(/\\/g, '/') : initial_model;
331
- cds.env.requires[service] = requires[service] = { kind: version, model };
332
- await write(package_json, JSON.stringify(conf, null, ' '));
332
+ let package_json_updated = false;
333
+ for (let service of services) {
334
+ if (!requires[service]) {
335
+ const initial_model = path.relative(cwd, dest);
336
+ const model = isLinux() ? initial_model.replace(/\\/g, '/') : initial_model;
337
+ cds.env.requires[service] = requires[service] = { kind: version, model };
338
+ await write(package_json, JSON.stringify(conf, null, ' '));
339
+ package_json_updated = true;
340
+ }
341
+ }
342
+ if (package_json_updated) {
333
343
  console.log(`[cds] - updated ./package.json`);
334
344
  }
335
345
  }
336
346
 
337
347
  async function postProcess(filePath, options, csn, cwd) {
338
- const service = _getServiceName(csn);
348
+ const services = _getServiceNames(csn);
339
349
  if (options.out) options.out = _validateAndComputeOutputFilePath(options.out, options.as, filePath);
340
350
  const version = options.inputFileVersion;
341
351
  const result = await _getResult(csn, options.as, options.out || filePath.replace(/\.[^.]+$/, ''), options.force, version);
342
- const written = options.dry || await _write(result, service, cwd);
343
- const registered = options.dry || options.no_save || await _updatePackageJson(result[1].replace(/\.[^.]+$/, ''), service, version, cwd);
352
+ const written = options.dry || await _write(result, services, cwd);
353
+ const registered = options.dry || options.no_save || await _updatePackageJson(result[1].replace(/\.[^.]+$/, ''), services, version, cwd);
344
354
  if (options.dry) return console.log(result[0]);
345
355
  return Promise.all([written, registered]);
346
356
  }
@@ -353,20 +363,20 @@ async function identifyFile(filepath) {
353
363
  // based on the file content determine if it is openapi or asyncapi file and return the correct type
354
364
  filepath = await isValidInputFile(path.resolve(process.cwd(), filepath));
355
365
  const src = await getContentFromFile(filepath);
356
- //for openapi
366
+ // for openapi
357
367
  let jsonSrc = JSON.parse(src);
358
368
  if (jsonSrc.hasOwnProperty('openapi') || jsonSrc.hasOwnProperty('swagger')) {
359
369
  return "openapi";
360
- } else if (jsonSrc.hasOwnProperty('asyncapi')){
361
- return "asyncapi";
370
+ } else if (jsonSrc.hasOwnProperty('asyncapi')) {
371
+ return "asyncapi";
362
372
  }
363
373
  } else
364
374
  return extension;
365
375
  }
366
376
 
367
- function isLinux(){
368
- let platform = process.platform
369
- if (platform === 'linux' || platform === 'win32'){
377
+ function isLinux() {
378
+ let platform = process.platform;
379
+ if (platform === 'linux' || platform === 'win32') {
370
380
  return true;
371
381
  }
372
382
  }
@@ -15,20 +15,21 @@ module.exports = Object.assign(cds_import, {
15
15
  });
16
16
 
17
17
  /**
18
- * This is the import API function to generate CSN from XML/EDMX files.
19
- * @param {string} filepath
20
- * - a single valid filepath
21
- * @param {{} | {keepNamespace:_keepNamespace, includeNamespaces:_includeNamespaces...}} options
22
- * - an options object for importing OData files specifying the keepNamespace, includeNamespaces options
23
- * - Default values for OData V2: {keepNamespace: false, includeNamespaces:"edmx,m,sap"}
24
- * - Default values for OData V4: {keepNamespace: false, includeNamespaces:"edmx"}
25
- * - optional parameters
26
- * - other import options not supported
27
- * @returns {object} CSN
28
- */
18
+ * This is the import API function to generate CSN from XML/EDMX files.
19
+ * @param {string} filepath
20
+ * - a single valid filepath
21
+ * @param {{} | {keepNamespace:_keepNamespace, includeNamespaces:_includeNamespaces...}} options
22
+ * - an options object for importing OData files specifying the keepNamespace, includeNamespaces options
23
+ * - Default values for OData V2: {keepNamespace: false, includeNamespaces:"edmx,m,sap"}
24
+ * - Default values for OData V4: {keepNamespace: false, includeNamespaces:"edmx"}
25
+ * - optional parameters
26
+ * - other import options not supported
27
+ * @returns {object} CSN
28
+ */
29
29
  async function cds_import(filepath, options = { keepNamespace: false }) {
30
30
  // identifies the file and calls the respective api
31
31
  let fileType = await common.identifyFile(filepath);
32
+
32
33
  let csn;
33
34
  switch (fileType) {
34
35
  case "edmx":
@@ -47,17 +48,17 @@ async function cds_import(filepath, options = { keepNamespace: false }) {
47
48
  }
48
49
 
49
50
  /**
50
- * This is the import API function to generate CSN from XML/EDMX files.
51
- * @param {string} filepath
52
- * - a single valid filepath
53
- * @param {{} | {keepNamespace:_keepNamespace, includeNamespaces:_includeNamespaces...}} options
54
- * - an options object specifying the keepNamespace, includeNamespaces options on how CSN is to be generated
55
- * - Default values for OData V2: {keepNamespace: false, includeNamespaces:"edmx,m,sap"}
56
- * - Default values for OData V4: {keepNamespace: false, includeNamespaces:"edmx"}
57
- * - optional parameters
58
- * - other import options not supported
59
- * @returns {object} CSN
60
- */
51
+ * This is the import API function to generate CSN from XML/EDMX files.
52
+ * @param {string} filepath
53
+ * - a single valid filepath
54
+ * @param {{} | {keepNamespace:_keepNamespace, includeNamespaces:_includeNamespaces...}} options
55
+ * - an options object specifying the keepNamespace, includeNamespaces options on how CSN is to be generated
56
+ * - Default values for OData V2: {keepNamespace: false, includeNamespaces:"edmx,m,sap"}
57
+ * - Default values for OData V4: {keepNamespace: false, includeNamespaces:"edmx"}
58
+ * - optional parameters
59
+ * - other import options not supported
60
+ * @returns {object} CSN
61
+ */
61
62
  async function cds_import_from_edmx(filepath, options = { keepNamespace: false }) {
62
63
  // validates and reads the input file
63
64
  filepath = await common.isValidInputFile(path.resolve(process.cwd(), filepath));
@@ -73,18 +74,18 @@ async function cds_import_from_edmx(filepath, options = { keepNamespace: false }
73
74
  odataOptions.namespaces = [];
74
75
  if (odataOptions.include_namespaces) odata.getNamespaces(odataOptions);
75
76
  let csn = await odata.edmx2csn(src, !odataOptions.keep_namespace && filepath, odataOptions);
76
- //reading the file version
77
+ // reading the file version
77
78
  options.odataVersion = odataOptions.odataVersion;
78
79
  // return the csn
79
80
  return csn;
80
81
  }
81
82
 
82
83
  /**
83
- * This is the import API function to generate CSN from openapi files.
84
- * @param {string} filepath
85
- * - a single valid filepath
86
- * @returns {object} CSN
87
- */
84
+ * This is the import API function to generate CSN from openapi files.
85
+ * @param {string} filepath
86
+ * - a single valid filepath
87
+ * @returns {object} CSN
88
+ */
88
89
  async function cds_import_from_openapi(filepath, options = {}) {
89
90
  // validates the input file
90
91
  filepath = await common.isValidInputFile(path.resolve(process.cwd(), filepath));
@@ -94,12 +95,12 @@ async function cds_import_from_openapi(filepath, options = {}) {
94
95
  return csn;
95
96
  }
96
97
 
97
- /**
98
- * This is the import API function to generate CSN from asyncapi files.
99
- * @param {string} filepath
100
- * - a single valid filepath
101
- * @returns {object} CSN
102
- */
98
+ /**
99
+ * This is the import API function to generate CSN from asyncapi files.
100
+ * @param {string} filepath
101
+ * - a single valid filepath
102
+ * @returns {object} CSN
103
+ */
103
104
  async function cds_import_from_asyncapi(filepath, options = {}) {
104
105
  // validates the input file
105
106
  filepath = await common.isValidInputFile(path.resolve(process.cwd(), filepath));
@@ -107,4 +108,4 @@ async function cds_import_from_asyncapi(filepath, options = {}) {
107
108
  let csn = asyncapi.asyncapi2csn(src);
108
109
  options.inputFileVersion = 'odata';
109
110
  return csn;
110
- }
111
+ }
package/lib/index.js CHANGED
@@ -1,19 +1,14 @@
1
- const cds = require('./cds')
2
- const compile_desc = Reflect.getOwnPropertyDescriptor(cds,'compile')
3
-
4
- // extending cds to lazy-load additional submodules provided by cds-dk
5
- module.exports = Object.defineProperties (cds, {
6
-
7
- import: {enumerable:true, get:()=> require('./import/importapi')},
1
+ const cds = module.exports = require('./cds')
2
+ cds.extend (cds.constructor) .with (class {
3
+ get import() { return super.import = require('./import/importapi') }
4
+ })
8
5
 
9
- compile: {enumerable:true, get:()=> {
10
- // lazy-extending cds.compile.to only when cds.compile getter is invoked
11
- // otherwise we might cause cds.env being invoked too early.
12
- const compile = compile_desc.value || compile_desc.get.call(cds)
13
- if (!Reflect.getOwnPropertyDescriptor(compile.to, 'openapi'))
14
- Object.defineProperties (compile.to, {
15
- openapi: {enumerable:true, get:()=> require('./compile/openapi')}
16
- })
17
- return compile
18
- }},
6
+ cds.extend (cds.compile.to.constructor) .with (class {
7
+ get asyncapi() { return super.asyncapi = require('./compile/asyncapi') }
8
+ get openapi() { return super.openapi = require('./compile/openapi') }
9
+ get xsuaa(){ return super.xsuaa = require('./compile/to-xsuaa') }
10
+ 'edmx-v2'(csn,o) { return cds.compile.to.edmx(csn,{...o,flavor:'v2'}) }
11
+ 'edmx-v4'(csn,o) { return cds.compile.to.edmx(csn,{...o,flavor:'v4'}) }
12
+ 'edmx-w4'(csn,o) { return cds.compile.to.edmx(csn,{...o,flavor:'w4'}) }
13
+ 'edmx-x4'(csn,o) { return cds.compile.to.edmx(csn,{...o,flavor:'x4'}) }
19
14
  })