@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.
- package/bin/activate.js +15 -7
- package/bin/add.js +29 -15
- package/bin/bind.js +49 -116
- package/bin/build.js +114 -0
- package/bin/cds.js +67 -24
- package/bin/compile/index.js +2 -2
- package/bin/deploy/index.js +46 -39
- package/bin/deploy/to-hana.js +11 -8
- package/bin/deploy/to-postgres.js +8 -2
- package/bin/deploy/to-sqlite.js +0 -1
- package/bin/env.js +75 -41
- package/bin/eval.js +3 -3
- package/bin/extend.js +17 -10
- package/bin/help.js +22 -21
- package/bin/import.js +10 -7
- package/bin/init.js +38 -17
- package/bin/login.js +69 -55
- package/bin/logout.js +12 -9
- package/bin/migrate.js +10 -4
- package/bin/pull.js +12 -5
- package/bin/push.js +24 -13
- package/bin/repl.js +1 -0
- package/bin/run.js +25 -0
- package/bin/subscribe.js +13 -8
- package/bin/unsubscribe.js +15 -8
- package/bin/upgrade.js +15 -9
- package/bin/util/log.js +24 -0
- package/bin/version.js +124 -0
- package/bin/watch.js +1 -35
- package/bin/watched.js +39 -0
- package/lib/bind/KubernetesApiAccessor.js +2 -2
- package/lib/bind/bindingManager.js +1 -1
- package/lib/bind/bindingUtil.js +0 -9
- package/lib/bind/cfKeyProvider.js +10 -72
- package/lib/bind/index.js +114 -0
- package/lib/bind/kubernetesCredentialsProvider.js +2 -2
- package/lib/bind/userCdsrcJsonStorageProvider.js +7 -44
- package/lib/build/buildTaskEngine.js +355 -0
- package/lib/build/buildTaskFactory.js +284 -0
- package/lib/build/buildTaskHandler.js +240 -0
- package/lib/build/buildTaskProvider.js +22 -0
- package/lib/build/buildTaskProviderFactory.js +182 -0
- package/lib/build/constants.js +56 -0
- package/lib/build/index.js +21 -0
- package/lib/build/provider/buildTaskHandlerEdmx.js +83 -0
- package/lib/build/provider/buildTaskHandlerFeatureToggles.js +132 -0
- package/lib/build/provider/buildTaskHandlerInternal.js +228 -0
- package/lib/build/provider/buildTaskProviderInternal.js +370 -0
- package/lib/build/provider/fiori/index.js +167 -0
- package/lib/build/provider/hana/2migration.js +179 -0
- package/lib/build/provider/hana/index.js +522 -0
- package/lib/build/provider/hana/migrationtable.js +472 -0
- package/lib/build/provider/hana/template/.hdiconfig-all +163 -0
- package/lib/build/provider/hana/template/.hdiconfig-cloud +137 -0
- package/lib/build/provider/hana/template/.hdinamespace +4 -0
- package/lib/build/provider/hana/template/package.json +12 -0
- package/lib/build/provider/hana/template/undeploy.json +5 -0
- package/lib/build/provider/java/index.js +93 -0
- package/lib/build/provider/java-cf/index.js +1 -0
- package/lib/build/provider/mtx/index.js +37 -0
- package/lib/build/provider/mtx/resourcesTarBuilder.js +94 -0
- package/lib/build/provider/mtx-extension/index.js +131 -0
- package/lib/build/provider/mtx-sidecar/index.js +138 -0
- package/lib/build/provider/node-cf/index.js +1 -0
- package/lib/build/provider/nodejs/index.js +178 -0
- package/lib/build/util.js +263 -0
- package/lib/cds.js +9 -21
- package/lib/client/auth_manager.js +39 -16
- package/lib/client/helper/dependency_helper.js +7 -6
- package/lib/client/push.js +2 -1
- package/lib/client/settings_manager.js +10 -39
- package/lib/deploy/to-hana/hana.js +273 -0
- package/lib/deploy/to-hana/hdiDeployUtil.js +68 -0
- package/lib/deploy/to-hana/mtaUtil.js +171 -0
- package/lib/import/asyncapi/importAsyncAPI.js +3 -2
- package/lib/import/asyncapi/index.js +5 -2
- package/lib/import/asyncapi/parserContext.js +67 -26
- package/lib/import/asyncapi/utils.js +34 -3
- package/lib/import/common.js +40 -30
- package/lib/import/importapi.js +36 -35
- package/lib/index.js +12 -17
- package/lib/init/constants.js +36 -71
- package/lib/init/index.js +18 -52
- package/lib/init/template/_merging/registry-mta.js +21 -3
- package/lib/init/template/approuter/files/mta.yaml.hbs +29 -29
- package/lib/init/template/approuter/files/values.yaml.hbs +5 -5
- package/lib/init/template/approuter/files/xs-app.json.hbs +8 -2
- package/lib/init/template/approuter/index.js +7 -8
- package/lib/init/template/auditlog/files/mta.yaml.hbs +5 -5
- package/lib/init/template/auditlog/files/package.json.hbs +13 -13
- package/lib/init/template/auditlog/index.js +3 -3
- package/lib/init/template/cf-manifest/files/manifest.yml.hbs +22 -22
- package/lib/init/template/cf-manifest/files/services-manifest.yml.hbs +3 -3
- package/lib/init/template/connectivity/files/mta.yaml.hbs +14 -0
- package/lib/init/template/connectivity/files/package.json.hbs +17 -0
- package/lib/init/template/connectivity/index.js +21 -4
- package/lib/init/template/data/index.js +5 -1
- package/lib/init/template/destination/files/mta.yaml.hbs +14 -0
- package/lib/init/template/destination/files/package.json.hbs +17 -0
- package/lib/init/template/{destinations → destination}/index.js +19 -13
- package/lib/init/template/enterprise-messaging/files/event-mesh.json.hbs +3 -3
- package/lib/init/template/enterprise-messaging/files/mta.yaml.hbs +5 -5
- package/lib/init/template/enterprise-messaging/files/package.json.hbs +9 -9
- package/lib/init/template/enterprise-messaging/files/xs-security.json.hbs +19 -0
- package/lib/init/template/enterprise-messaging/index.js +27 -6
- package/lib/init/template/enterprise-messaging-shared/files/event-mesh.json.hbs +3 -3
- package/lib/init/template/enterprise-messaging-shared/files/mta.yaml.hbs +5 -5
- package/lib/init/template/enterprise-messaging-shared/files/package.json.hbs +9 -9
- package/lib/init/template/enterprise-messaging-shared/index.js +4 -5
- package/lib/init/template/extensibility/files/package.json.hbs +10 -10
- package/lib/init/template/extensibility/index.js +8 -9
- package/lib/init/template/file-based-messaging/files/package.json.hbs +9 -9
- package/lib/init/template/file-based-messaging/index.js +3 -4
- package/lib/init/template/hana/files/db/package.json +1 -1
- package/lib/init/template/hana/files/mta.yaml.hbs +21 -21
- package/lib/init/template/hana/files/package.json.hbs +16 -22
- package/lib/init/template/hana/files/values.yaml.hbs +1 -1
- package/lib/init/template/hana/index.js +5 -15
- package/lib/init/template/helm/files/Chart.yaml.hbs +4 -4
- package/lib/init/template/helm/files/values.yaml.hbs +6 -6
- package/lib/init/template/helm/index.js +5 -10
- package/lib/init/template/helm/subcharts/content-deployment/Chart.yaml +2 -0
- package/lib/init/template/helm/subcharts/content-deployment/templates/_helpers.tpl +37 -31
- package/lib/init/template/helm/subcharts/content-deployment/templates/job.yaml +13 -14
- package/lib/init/template/helm/subcharts/content-deployment/templates/secret.yaml +2 -2
- package/lib/init/template/helm/subcharts/content-deployment/templates/service-account.yaml +1 -1
- package/lib/init/template/helm/subcharts/content-deployment/templates/service-binding.yaml +3 -3
- package/lib/init/template/helm/subcharts/content-deployment/values.md +116 -116
- package/lib/init/template/helm/subcharts/service-instance/Chart.yaml +2 -0
- package/lib/init/template/helm/subcharts/service-instance/templates/_helpers.tpl +9 -9
- package/lib/init/template/helm/subcharts/service-instance/templates/serviceinstance.yaml +2 -2
- package/lib/init/template/helm/subcharts/service-instance/values.md +15 -15
- package/lib/init/template/helm/subcharts/web-application/Chart.yaml +2 -0
- package/lib/init/template/helm/subcharts/web-application/templates/NOTES.txt +15 -0
- package/lib/init/template/helm/subcharts/web-application/templates/_helpers.tpl +23 -23
- package/lib/init/template/helm/subcharts/web-application/templates/api-rule.yaml +4 -4
- package/lib/init/template/helm/subcharts/web-application/templates/deployment.yaml +17 -17
- package/lib/init/template/helm/subcharts/web-application/templates/network-policy.yaml +24 -3
- package/lib/init/template/helm/subcharts/web-application/templates/pod-disruption-budget.yaml +3 -3
- package/lib/init/template/helm/subcharts/web-application/templates/secret.yaml +2 -2
- package/lib/init/template/helm/subcharts/web-application/templates/service-account.yaml +1 -1
- package/lib/init/template/helm/subcharts/web-application/templates/service-binding.yaml +3 -3
- package/lib/init/template/helm/subcharts/web-application/templates/service.yaml +3 -3
- package/lib/init/template/helm/subcharts/web-application/values.md +141 -123
- package/lib/init/template/helm/subcharts/web-application/values.schema.json +7 -0
- package/lib/init/template/helm/subcharts/web-application/values.yaml +1 -0
- package/lib/init/template/html5-repo/index.js +4 -5
- package/lib/init/template/java/index.js +5 -5
- package/lib/init/template/kibana-logging/files/mta.yaml.hbs +5 -5
- package/lib/init/template/kibana-logging/files/package.json.hbs +9 -9
- package/lib/init/template/kibana-logging/index.js +3 -4
- package/lib/init/template/lint/index.js +3 -3
- package/lib/init/template/mta/files/mta.yaml.hbs +14 -14
- package/lib/init/template/mta/files/package.json +5 -0
- package/lib/init/template/mta/index.js +12 -13
- package/lib/init/template/mtx/index.js +2 -2
- package/lib/init/template/multitenancy/files/mta.yaml.hbs +29 -27
- package/lib/init/template/multitenancy/files/package.json.hbs +17 -14
- package/lib/init/template/multitenancy/files/package.sidecar.json.hbs +7 -7
- package/lib/init/template/multitenancy/files/values.yaml.hbs +19 -19
- package/lib/init/template/multitenancy/index.js +14 -16
- package/lib/init/template/nodejs/files/package.json.hbs +1 -1
- package/lib/init/template/nodejs/index.js +5 -8
- package/lib/init/template/redis-messaging/files/mta.yaml.hbs +5 -5
- package/lib/init/template/redis-messaging/files/package.json.hbs +9 -9
- package/lib/init/template/redis-messaging/index.js +4 -5
- package/lib/init/template/sample/files/app/_i18n/i18n.properties +43 -0
- package/lib/init/template/sample/files/app/_i18n/i18n_de.properties +14 -0
- package/lib/init/template/sample/files/app/admin-books/fiori-service.cds +114 -0
- package/lib/init/template/sample/files/app/admin-books/webapp/Component.js +8 -0
- package/lib/init/template/sample/files/app/admin-books/webapp/i18n/i18n.properties +11 -0
- package/lib/init/template/sample/files/app/admin-books/webapp/manifest.json +129 -0
- package/lib/init/template/sample/files/app/appconfig/fioriSandboxConfig.json +57 -0
- package/lib/init/template/sample/files/app/common.cds +263 -0
- package/lib/init/template/sample/files/app/index.html +30 -0
- package/lib/init/template/sample/files/app/services.cds +5 -0
- package/lib/init/template/sample/files/db/data/sap.capire.bookshop-Authors.csv +5 -0
- package/lib/init/template/sample/files/db/data/sap.capire.bookshop-Books.csv +6 -0
- package/lib/init/template/sample/files/db/data/sap.capire.bookshop-Books_texts.csv +5 -0
- package/lib/init/template/sample/files/db/data/sap.capire.bookshop-Genres.csv +16 -0
- package/lib/init/template/sample/files/db/schema.cds +31 -0
- package/lib/init/template/sample/files/nodejs/admin-service.js +12 -0
- package/lib/init/template/sample/files/nodejs/cat-service.js +26 -0
- package/lib/init/template/sample/files/srv/admin-service.cds +5 -0
- package/lib/init/template/sample/files/srv/cat-service.cds +16 -0
- package/lib/init/template/sample/index.js +24 -0
- package/lib/init/template/sample-tiny/index.js +39 -0
- package/lib/init/template/samples/index.js +5 -56
- package/lib/init/template/sqlite/files/package.json.hbs +13 -13
- package/lib/init/template/sqlite/index.js +2 -2
- package/lib/init/template/templateBase.js +24 -1
- package/lib/init/template/toggles/files/package.json.hbs +10 -10
- package/lib/init/template/toggles/index.js +3 -3
- package/lib/init/template/typer/files/gitignore +1 -0
- package/lib/init/template/typer/files/package.json +8 -0
- package/lib/init/template/typer/files/xsconfig.json +9 -0
- package/lib/init/template/typer/index.js +36 -0
- package/lib/init/template/xsuaa/files/mta.yaml.hbs +12 -12
- package/lib/init/template/xsuaa/files/package.json.hbs +13 -13
- package/lib/init/template/xsuaa/files/values.yaml.hbs +8 -8
- package/lib/init/template/xsuaa/index.js +8 -19
- package/lib/init/util/merge.js +73 -59
- package/lib/init/util/mvn.js +21 -17
- package/lib/init/util/projectReader.js +49 -87
- package/lib/init/util/xml.js +14 -23
- package/lib/util/cfUtil.js +366 -0
- package/lib/util/command.js +3 -3
- package/lib/util/gitUtil.js +55 -0
- package/lib/util/version.js +27 -0
- package/npm-shrinkwrap.json +339 -277
- package/package.json +6 -6
- package/CHANGELOG.md +0 -1453
- package/bin/build/all.js +0 -88
- package/bin/build/index.js +0 -82
- package/lib/compile/index.js +0 -14
- /package/lib/init/template/{samples → sample-tiny}/files/nodejs/db/data/my.bookshop-Books.csv +0 -0
- /package/lib/init/template/{samples → sample-tiny}/files/nodejs/db/data-model.cds +0 -0
- /package/lib/init/template/{samples → sample-tiny}/files/nodejs/srv/cat-service.cds.hbs +0 -0
|
@@ -6,11 +6,11 @@ const axios = require('axios');
|
|
|
6
6
|
const cds = require('../cds');
|
|
7
7
|
const DEBUG = cds.debug('cli');
|
|
8
8
|
const { requireGlobal } = require('./helper/dependency_helper');
|
|
9
|
-
const { getAppFromSuggestions,
|
|
9
|
+
const { getAppFromSuggestions, getSubdomain } = require('./helper/cf_helper');
|
|
10
10
|
const isBas = require('./helper/env_helper');
|
|
11
11
|
const Question = require('./helper/question');
|
|
12
12
|
const { CliError } = require('./helper/errors');
|
|
13
|
-
const { httpSchema, httpsSchema,
|
|
13
|
+
const { httpSchema, httpsSchema, schemaRegex, localhostRegex } = require('./helper/url_helper');
|
|
14
14
|
const { capitalize } = require('./helper/string_helper');
|
|
15
15
|
|
|
16
16
|
const { ParamCollection, Persistence } = require('./params');
|
|
@@ -64,10 +64,7 @@ function getProjectFolder(params) {
|
|
|
64
64
|
const maybeExistentPath = path.resolve(params.get('projectFolder'));
|
|
65
65
|
return maybeExistentPath;
|
|
66
66
|
}
|
|
67
|
-
|
|
68
|
-
? params.get('subdomain')
|
|
69
|
-
: '.';
|
|
70
|
-
return fs.realpathSync(existentPath);
|
|
67
|
+
return fs.realpathSync('.');
|
|
71
68
|
}
|
|
72
69
|
|
|
73
70
|
async function getAppUrlAndSubdomainFromSuggestions(params) {
|
|
@@ -109,7 +106,7 @@ async function getTokenBaseUrl(params, renewUrl) {
|
|
|
109
106
|
};
|
|
110
107
|
|
|
111
108
|
let existingPath;
|
|
112
|
-
const oauthPaths = [OAUTH_PATH_STREAMLINED_MTX
|
|
109
|
+
const oauthPaths = [OAUTH_PATH_STREAMLINED_MTX];
|
|
113
110
|
for (const path of oauthPaths) {
|
|
114
111
|
try {
|
|
115
112
|
await axios.head(getBaseUrl(path).toString());
|
|
@@ -122,7 +119,7 @@ async function getTokenBaseUrl(params, renewUrl) {
|
|
|
122
119
|
throw error;
|
|
123
120
|
}
|
|
124
121
|
}
|
|
125
|
-
existingPath = existingPath ?? OAUTH_PATH_OLD_MTX;
|
|
122
|
+
existingPath = existingPath ?? OAUTH_PATH_OLD_MTX; // REVISIT can this just be included in the array?
|
|
126
123
|
return getBaseUrl(existingPath).toString();
|
|
127
124
|
}
|
|
128
125
|
|
|
@@ -218,12 +215,7 @@ class SettingsManager {
|
|
|
218
215
|
}
|
|
219
216
|
|
|
220
217
|
static async updateUrls(params, logout, loadedAppUrl) {
|
|
221
|
-
async function
|
|
222
|
-
function needsSubdomain() {
|
|
223
|
-
// Subdomain needed for token retrieval.
|
|
224
|
-
return params.has('appUrl') && !localhostRegex.test(params.get('appUrl')) && !params.get('skipToken');
|
|
225
|
-
}
|
|
226
|
-
|
|
218
|
+
async function addAppUrl() {
|
|
227
219
|
// Prefix URL schema
|
|
228
220
|
if (params.has('appUrl')) {
|
|
229
221
|
const appUrl = params.get('appUrl');
|
|
@@ -237,37 +229,16 @@ class SettingsManager {
|
|
|
237
229
|
}
|
|
238
230
|
}
|
|
239
231
|
|
|
240
|
-
if (!logout) {
|
|
232
|
+
if (!logout && !params.has('appUrl')) {
|
|
241
233
|
// Get appUrl from CF
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
await getAppUrlAndSubdomainFromSuggestions(params);
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
// Get subdomain from CF
|
|
248
|
-
if (!params.has('subdomain') && needsSubdomain()) {
|
|
249
|
-
DEBUG?.('Subdomain not given');
|
|
250
|
-
const appName = await getAppName(params.get('appUrl'));
|
|
251
|
-
if (appName) {
|
|
252
|
-
params.set('subdomain', await getSubdomainFromCfAndNotify(appName));
|
|
253
|
-
}
|
|
254
|
-
}
|
|
234
|
+
DEBUG?.('App URL not given');
|
|
235
|
+
await getAppUrlAndSubdomainFromSuggestions(params);
|
|
255
236
|
}
|
|
256
237
|
|
|
257
238
|
// Check required param: appUrl
|
|
258
239
|
if (!params.has('appUrl')) {
|
|
259
240
|
throw new CliError('App URL not given. Please specify it or log in to Cloud Foundry and repeat this command.');
|
|
260
241
|
}
|
|
261
|
-
|
|
262
|
-
// Check required param: subdomain
|
|
263
|
-
if (!params.has('subdomain') && needsSubdomain()) {
|
|
264
|
-
const subdomain = extractSubdomain(params.get('appUrl'));
|
|
265
|
-
if (!subdomain) {
|
|
266
|
-
throw new CliError('Subdomain not given');
|
|
267
|
-
}
|
|
268
|
-
params.set('subdomain', subdomain);
|
|
269
|
-
console.log('Subdomain determined from app URL:', subdomain);
|
|
270
|
-
}
|
|
271
242
|
}
|
|
272
243
|
async function renewTokenUrl() {
|
|
273
244
|
const renewUrl = params.get('appUrl') !== loadedAppUrl;
|
|
@@ -276,7 +247,7 @@ class SettingsManager {
|
|
|
276
247
|
}
|
|
277
248
|
}
|
|
278
249
|
|
|
279
|
-
await
|
|
250
|
+
await addAppUrl();
|
|
280
251
|
|
|
281
252
|
if (!logout && !params.get('skipToken')) {
|
|
282
253
|
await renewTokenUrl();
|
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
const cp = require('child_process');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const util = require('util');
|
|
4
|
+
|
|
5
|
+
const fs = require('fs').promises;
|
|
6
|
+
|
|
7
|
+
const cds = require('../../../lib/cds');
|
|
8
|
+
|
|
9
|
+
const { build } = require('../../build');
|
|
10
|
+
const buildConstants = require('../../build/constants');
|
|
11
|
+
|
|
12
|
+
const hdiDeployUtil = require('./hdiDeployUtil');
|
|
13
|
+
const cfUtil = require('../../util/cfUtil');
|
|
14
|
+
const gitUtil = require('../../util/gitUtil');
|
|
15
|
+
const mtaUtil = require('./mtaUtil');
|
|
16
|
+
|
|
17
|
+
const { bold, info } = require('../../util/term');
|
|
18
|
+
const { CliError } = require('../../client/helper/errors');
|
|
19
|
+
|
|
20
|
+
const { bind } = require('../../bind');
|
|
21
|
+
|
|
22
|
+
const UTF_8 = 'utf-8';
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class HanaDeployer {
|
|
26
|
+
|
|
27
|
+
constructor() {
|
|
28
|
+
this.execAsync = util.promisify(cp.exec);
|
|
29
|
+
this.spawnSync = cp.spawnSync;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
getFromEnv(...varNames) {
|
|
33
|
+
const result = {}
|
|
34
|
+
for (const varName of varNames) {
|
|
35
|
+
if (process.env[varName]) {
|
|
36
|
+
try {
|
|
37
|
+
result[varName] = JSON.parse(process.env[varName]);
|
|
38
|
+
} catch (err) {
|
|
39
|
+
throw new Error(`Error parsing environment variable ${varName}`);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return result;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// arg object
|
|
47
|
+
// async deploy(model, serviceName, tunnelAddress, buildTaskOptions, vcapFile, undeployWhitelist, hdiOptions, bindCallback) { // NOSONAR
|
|
48
|
+
async deploy(options = {}) { // NOSONAR
|
|
49
|
+
let { model, serviceName, tunnelAddress, vcapFile, undeployWhitelist, hdiOptions } = options;
|
|
50
|
+
|
|
51
|
+
if (model) {
|
|
52
|
+
throw new CliError('Specifying a model for hana deployment is not supported.');
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
console.log(`${bold('Starting deploy to SAP HANA ...')}`);
|
|
56
|
+
if (vcapFile) {
|
|
57
|
+
console.log(`Using VCAP_SERVICES from file ${vcapFile} (beta feature).`);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const projectPath = cds.root;
|
|
61
|
+
|
|
62
|
+
const buildResults = await this._build();
|
|
63
|
+
|
|
64
|
+
let globalVcapEnv = vcapFile ? await this._loadEnvFile(vcapFile) : {};
|
|
65
|
+
globalVcapEnv = { ...globalVcapEnv, ...this.getFromEnv('VCAP_SERVICES', 'SERVICE_REPLACEMENTS') };
|
|
66
|
+
if (process.env.TARGET_CONTAINER) {
|
|
67
|
+
globalVcapEnv.TARGET_CONTAINER = process.env.TARGET_CONTAINER;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
for (const buildResult of buildResults) {
|
|
71
|
+
let vcapEnv = globalVcapEnv;
|
|
72
|
+
let serviceKeyName;
|
|
73
|
+
const currentModelFolder = buildResult.task.dest;
|
|
74
|
+
|
|
75
|
+
if (undeployWhitelist) {
|
|
76
|
+
console.log('Writing undeploy.json');
|
|
77
|
+
await fs.write(path.join(currentModelFolder, 'undeploy.json'), JSON.stringify(undeployWhitelist, null, 2));
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const hasVCAPEnv = Object.keys(vcapEnv).length > 0;
|
|
81
|
+
if (!serviceName && hasVCAPEnv) {
|
|
82
|
+
await fs.mkdir(currentModelFolder, { recursive: true });
|
|
83
|
+
} else {
|
|
84
|
+
const { cfServiceInstanceName, cfServiceInstanceKeyName, serviceKey } =
|
|
85
|
+
await this._getOrCreateCFService(projectPath, currentModelFolder, serviceName, tunnelAddress);
|
|
86
|
+
serviceKeyName = cfServiceInstanceKeyName;
|
|
87
|
+
serviceName = serviceName || cfServiceInstanceName;
|
|
88
|
+
|
|
89
|
+
vcapEnv = this._getVCAPServicesEntry(cfServiceInstanceName, serviceKey);
|
|
90
|
+
|
|
91
|
+
if (options.storeCredentials) {
|
|
92
|
+
await this._addInstanceToDefaultEnvJson([currentModelFolder, projectPath], cfServiceInstanceName, serviceKey);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
hdiOptions = hdiOptions || {}
|
|
97
|
+
await hdiDeployUtil.deploy(currentModelFolder, vcapEnv, hdiOptions);
|
|
98
|
+
|
|
99
|
+
if (!hasVCAPEnv) {
|
|
100
|
+
const bindOptions = {
|
|
101
|
+
...options,
|
|
102
|
+
to: `${serviceName}:${serviceKeyName}`,
|
|
103
|
+
for: options.for,
|
|
104
|
+
kind: buildResult.task.for
|
|
105
|
+
}
|
|
106
|
+
await bind(bindOptions);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
if (options.storeCredentials) {
|
|
111
|
+
await gitUtil.ensureFileIsGitignored('default-env.json', projectPath);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
console.log(`If not already done, use ${info('cds add hana')} to configure the project for SAP HANA.\n`);
|
|
115
|
+
console.log(`Done.`);
|
|
116
|
+
|
|
117
|
+
return { buildResults };
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
async _getOrCreateCFService(projectPath, currentModelFolder, serviceName, tunnelAddress) {
|
|
122
|
+
const modelName = path.basename(currentModelFolder);
|
|
123
|
+
|
|
124
|
+
// get from param
|
|
125
|
+
let cfServiceInstanceMta;
|
|
126
|
+
let cfServiceInstanceName;
|
|
127
|
+
if (serviceName) {
|
|
128
|
+
cfServiceInstanceName = serviceName;
|
|
129
|
+
} else {
|
|
130
|
+
const cfServiceDescriptor = await mtaUtil.getHanaDbModuleDescriptor(projectPath, modelName);
|
|
131
|
+
cfServiceInstanceName = cfServiceDescriptor.hdiServiceName;
|
|
132
|
+
cfServiceInstanceMta = cfServiceDescriptor.hdiService
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
console.log();
|
|
136
|
+
this._validateServiceInstanceName(cfServiceInstanceName);
|
|
137
|
+
console.log(`Using container ${bold(cfServiceInstanceName)}`);
|
|
138
|
+
|
|
139
|
+
let cfConfig = cfServiceInstanceMta && cfServiceInstanceMta.parameters && cfServiceInstanceMta.parameters.config;
|
|
140
|
+
const serviceInstance = await this.createHanaService(cfServiceInstanceName, cfConfig);
|
|
141
|
+
|
|
142
|
+
const cfServiceInstanceKeyName = `${cfServiceInstanceName}-key`;
|
|
143
|
+
let serviceKey = await cfUtil.getOrCreateServiceKey(serviceInstance, cfServiceInstanceKeyName);
|
|
144
|
+
this._validateServiceKey(serviceKey, cfServiceInstanceKeyName);
|
|
145
|
+
|
|
146
|
+
if (tunnelAddress) {
|
|
147
|
+
console.log(`Using tunnel address ${bold(tunnelAddress)} (beta feature)`);
|
|
148
|
+
serviceKey = this._injectTunnelAddress(serviceKey, tunnelAddress)
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
return { cfServiceInstanceName, cfServiceInstanceKeyName, serviceKey, serviceInstance }
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
async createHanaService(instanceName, cfConfig) {
|
|
156
|
+
// hana or hanatrial, error if neither found
|
|
157
|
+
try {
|
|
158
|
+
return await cfUtil.getOrCreateService('hana', 'hdi-shared', instanceName, cfConfig);
|
|
159
|
+
} catch (error) {
|
|
160
|
+
if (error.command && /offering .* not found/i.test(error.command.stderr)) {
|
|
161
|
+
console.log(`Falling back to 'hanatrial'`);
|
|
162
|
+
return await cfUtil.getOrCreateService('hanatrial', 'hdi-shared', instanceName, cfConfig);
|
|
163
|
+
}
|
|
164
|
+
else if (error.command && /no database/i.test(error.command.stderr)) {
|
|
165
|
+
console.log(`No database connected to 'hana' service. Falling back to 'hanatrial'`);
|
|
166
|
+
return await cfUtil.getOrCreateService('hanatrial', 'hdi-shared', instanceName, cfConfig);
|
|
167
|
+
}
|
|
168
|
+
throw error;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
_validateServiceKey(serviceKey, cfServiceInstanceKey) {
|
|
174
|
+
if (!serviceKey) {
|
|
175
|
+
throw new Error(`Could not create service key ${bold(cfServiceInstanceKey)}.`);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
const fields = ['schema', 'user', 'password', 'url'];
|
|
179
|
+
for (const field of fields) {
|
|
180
|
+
if (!serviceKey[field]) {
|
|
181
|
+
throw new Error(`Service key is missing mandatory field '${field}'. Make sure you are ${bold('not')} using a managed service.`);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
async _build() {
|
|
188
|
+
const buildTaskOptions = {
|
|
189
|
+
for: buildConstants.BUILD_TASK_HANA
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
console.log(`Running build`);
|
|
193
|
+
const buildResults = await build(buildTaskOptions);
|
|
194
|
+
return buildResults;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
async _loadEnvFile(defaultEnvFile) {
|
|
198
|
+
try {
|
|
199
|
+
const content = await fs.readFile(defaultEnvFile);
|
|
200
|
+
return JSON.parse(content);
|
|
201
|
+
} catch (err) {
|
|
202
|
+
throw new Error(`Error reading default env file: ${err.message}`);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
async _addInstanceToDefaultEnvJson(currentFolders, serviceInstanceName, serviceKey) {
|
|
208
|
+
for (const currentFolder of currentFolders) {
|
|
209
|
+
let defaultEnvJson = {};
|
|
210
|
+
const defaultEnvJsonPath = path.join(currentFolder, 'default-env.json');
|
|
211
|
+
|
|
212
|
+
try {
|
|
213
|
+
defaultEnvJson = JSON.parse(await fs.readFile(defaultEnvJsonPath, UTF_8));
|
|
214
|
+
} catch (err) {
|
|
215
|
+
// ignore any errors
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
defaultEnvJson.VCAP_SERVICES = defaultEnvJson.VCAP_SERVICES || {};
|
|
219
|
+
for (const serviceKey of Object.keys(defaultEnvJson.VCAP_SERVICES)) {
|
|
220
|
+
defaultEnvJson.VCAP_SERVICES[serviceKey] = defaultEnvJson.VCAP_SERVICES[serviceKey].filter((service) => {
|
|
221
|
+
return (service.name !== serviceInstanceName);
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
const hanaEntry = this._getVCAPServicesEntry(serviceInstanceName, serviceKey)
|
|
226
|
+
Object.assign(defaultEnvJson, hanaEntry);
|
|
227
|
+
|
|
228
|
+
console.log(`Writing ${defaultEnvJsonPath}`);
|
|
229
|
+
await fs.mkdir(path.dirname(defaultEnvJsonPath), { recursive: true })
|
|
230
|
+
await fs.writeFile(defaultEnvJsonPath, JSON.stringify(defaultEnvJson, null, 2));
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
_getVCAPServicesEntry(serviceInstanceName, serviceKey) {
|
|
236
|
+
return {
|
|
237
|
+
VCAP_SERVICES: {
|
|
238
|
+
hana: [
|
|
239
|
+
{
|
|
240
|
+
name: serviceInstanceName,
|
|
241
|
+
tags: ['hana'],
|
|
242
|
+
credentials: serviceKey
|
|
243
|
+
}
|
|
244
|
+
]
|
|
245
|
+
}
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
_validateServiceInstanceName(serviceInstanceName) {
|
|
251
|
+
// valid service name chars: alpha-numeric, hyphens, and underscores
|
|
252
|
+
if (/[^\w-_]+/g.exec(serviceInstanceName)) {
|
|
253
|
+
throw new Error(`Service name ${serviceInstanceName} must only contain alpha-numeric, hyphens, and underscores.`);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
|
|
258
|
+
_injectTunnelAddress(serviceKey, tunnelAddress) {
|
|
259
|
+
if (!/\w+:\d+/.test(tunnelAddress)) {
|
|
260
|
+
throw new Error(`Invalid tunnel address '${tunnelAddress}' - must be in form 'host:port'`)
|
|
261
|
+
}
|
|
262
|
+
const [tunnelHost, tunnelPort] = tunnelAddress.split(':')
|
|
263
|
+
const { host, port } = serviceKey
|
|
264
|
+
serviceKey.host = tunnelHost
|
|
265
|
+
serviceKey.port = tunnelPort
|
|
266
|
+
serviceKey.url = serviceKey.url.replace(`${host}:${port}`, tunnelAddress)
|
|
267
|
+
serviceKey.hostname_in_certificate = host // make cert. verification happy, see xs2/hdideploy.js#527
|
|
268
|
+
serviceKey.url = serviceKey.url + (serviceKey.url.includes('?') ? '&' : '?') + 'hostNameInCertificate=' + host
|
|
269
|
+
return serviceKey
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
module.exports = new HanaDeployer();
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
const path = require('path');
|
|
2
|
+
const util = require('util');
|
|
3
|
+
|
|
4
|
+
const HDI_DEPLOY_LIB = '@sap/hdi-deploy';
|
|
5
|
+
|
|
6
|
+
class HdiDeployUtil {
|
|
7
|
+
|
|
8
|
+
async deploy(dbDir, vcapEnv = {}, options = {}) {
|
|
9
|
+
console.log(`Deploying to HANA from ${dbDir}`);
|
|
10
|
+
|
|
11
|
+
const hdiDeployLib = await this._loadHdiDeployLib(dbDir);
|
|
12
|
+
|
|
13
|
+
let deployerEnv = JSON.parse(JSON.stringify(process.env));
|
|
14
|
+
const hdiDeployOptions = deployerEnv.HDI_DEPLOY_OPTIONS ? JSON.parse(deployerEnv.HDI_DEPLOY_OPTIONS) : {};
|
|
15
|
+
delete hdiDeployOptions.root;
|
|
16
|
+
|
|
17
|
+
if (typeof hdiDeployLib.clean_env === 'function') {
|
|
18
|
+
deployerEnv = hdiDeployLib.clean_env(deployerEnv);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
if (vcapEnv.VCAP_SERVICES) {
|
|
22
|
+
deployerEnv.VCAP_SERVICES = JSON.stringify(vcapEnv.VCAP_SERVICES);
|
|
23
|
+
}
|
|
24
|
+
if (vcapEnv.SERVICE_REPLACEMENTS) {
|
|
25
|
+
deployerEnv.SERVICE_REPLACEMENTS = JSON.stringify(vcapEnv.SERVICE_REPLACEMENTS);
|
|
26
|
+
}
|
|
27
|
+
if (vcapEnv.TARGET_CONTAINER) {
|
|
28
|
+
deployerEnv.TARGET_CONTAINER = vcapEnv.TARGET_CONTAINER;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (options.autoUndeploy) {
|
|
32
|
+
console.log(`Hdi deployer automatically undeploys deleted resources using --auto-undeploy.`);
|
|
33
|
+
hdiDeployOptions.auto_undeploy = true;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (Object.entries(hdiDeployOptions).length > 0) {
|
|
37
|
+
deployerEnv.HDI_DEPLOY_OPTIONS = JSON.stringify(hdiDeployOptions);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const asyncDeploy = util.promisify(hdiDeployLib.deploy);
|
|
41
|
+
const response = await asyncDeploy(dbDir, deployerEnv);
|
|
42
|
+
if (response?.exitCode) {
|
|
43
|
+
let message = `HDI deployment failed with exit code ${response.exitCode}`;
|
|
44
|
+
if (response.signal) {
|
|
45
|
+
message += `. ${response.signal}`;
|
|
46
|
+
}
|
|
47
|
+
throw new Error(message);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
_loadHdiDeployLib(cwd) {
|
|
53
|
+
const searchPaths = [cwd, __dirname];
|
|
54
|
+
const libPath = require.resolve(path.join(HDI_DEPLOY_LIB, 'library'), { paths: searchPaths });
|
|
55
|
+
if (!libPath) {
|
|
56
|
+
throw new Error(`Required library '${HDI_DEPLOY_LIB}' not found in
|
|
57
|
+
${searchPaths.join('\n ')}
|
|
58
|
+
Add it either as a devDependency using 'npm install -D ${HDI_DEPLOY_LIB}' or install it globally using 'npm install -g ${HDI_DEPLOY_LIB}'.`);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
console.log(`Using HDI deployer from ${libPath}`)
|
|
62
|
+
|
|
63
|
+
// let any error go through and abort deploy
|
|
64
|
+
return require(libPath);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
module.exports = new HdiDeployUtil();
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
const cds = require('../../cds')
|
|
2
|
+
|
|
3
|
+
const fs = require('fs').promises
|
|
4
|
+
const {existsSync} = require('fs')
|
|
5
|
+
const path = require('path')
|
|
6
|
+
|
|
7
|
+
const HDI_CONTAINER_TYPES = ['com.sap.xs.hdi-container']
|
|
8
|
+
const UTF_8 = 'utf-8'
|
|
9
|
+
const MTA_YAML = 'mta.yaml'
|
|
10
|
+
const DEBUG = cds.debug('cli');
|
|
11
|
+
|
|
12
|
+
async function getHanaDbModuleDescriptor(projectPath, moduleName) {
|
|
13
|
+
// mta might be null if mta.yaml does not exist
|
|
14
|
+
const mta = await _getMta(projectPath)
|
|
15
|
+
const projectInfo = await _getProjectInfo(projectPath, mta)
|
|
16
|
+
const hdiService = _findHdiResource(mta, moduleName)
|
|
17
|
+
const appName = _getApplicationName(mta, moduleName, 'hdb')
|
|
18
|
+
|
|
19
|
+
return {
|
|
20
|
+
project: projectInfo,
|
|
21
|
+
appName: appName ? appName : `${projectInfo.name}-${moduleName}-deployer`,
|
|
22
|
+
hdiServiceName: hdiService ? hdiService.name : `${projectInfo.name}-${moduleName}`,
|
|
23
|
+
hdiService: hdiService
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
async function getServiceModuleDescriptor(projectPath, moduleName, moduleType) {
|
|
28
|
+
// mta might be null if mta.yaml does not exist
|
|
29
|
+
const mta = await _getMta(projectPath)
|
|
30
|
+
const projectInfo = await _getProjectInfo(projectPath, mta)
|
|
31
|
+
const appName = _getApplicationName(mta, moduleName, moduleType)
|
|
32
|
+
|
|
33
|
+
return {
|
|
34
|
+
project: projectInfo,
|
|
35
|
+
appName: appName ? appName : `${projectInfo.name}-${moduleName}`
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
async function _getProjectInfo(projectPath, mta) {
|
|
40
|
+
const details = {
|
|
41
|
+
}
|
|
42
|
+
// 1. use mta data
|
|
43
|
+
if (mta) {
|
|
44
|
+
details.id = mta.ID
|
|
45
|
+
details.description = mta.description
|
|
46
|
+
details.version = mta.version
|
|
47
|
+
if (mta.ID) {
|
|
48
|
+
details.name = mta.ID.replace(/\./g, '-')
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
// 2. use package.json data
|
|
52
|
+
const packageJsonPath = path.join(projectPath, 'package.json')
|
|
53
|
+
if (existsSync(packageJsonPath)) {
|
|
54
|
+
try {
|
|
55
|
+
const packageJson = JSON.parse((await fs.readFile(packageJsonPath, 'utf-8')).toString())
|
|
56
|
+
if (!details.description && packageJson.description) {
|
|
57
|
+
details.description = packageJson.description
|
|
58
|
+
}
|
|
59
|
+
if (!details.version && packageJson.version) {
|
|
60
|
+
details.version = packageJson.version
|
|
61
|
+
}
|
|
62
|
+
if (packageJson.name) {
|
|
63
|
+
let segments = packageJson.name.trim().split('/')
|
|
64
|
+
// scope as namespace
|
|
65
|
+
if (segments[0].startsWith('@')) {
|
|
66
|
+
segments[0] = segments[0].replace('@', '')
|
|
67
|
+
}
|
|
68
|
+
segments = segments.map(segment => segment.startsWith('@') ? encodeURIComponent(segment.replace('@', '')) : encodeURIComponent(segment))
|
|
69
|
+
if (!details.name) {
|
|
70
|
+
details.name = segments[segments.length - 1]
|
|
71
|
+
}
|
|
72
|
+
if (!details.id) {
|
|
73
|
+
details.id = segments.join('.')
|
|
74
|
+
}
|
|
75
|
+
if (!details.description) {
|
|
76
|
+
details.description = segments[segments.length - 1]
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
} catch (e) {
|
|
80
|
+
console.error(`Failed to load ${packageJsonPath} - skip application data`, e)
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
// 3. use project name and static default values
|
|
84
|
+
const projectName = path.basename(projectPath)
|
|
85
|
+
if (!details.name) {
|
|
86
|
+
details.name = projectName
|
|
87
|
+
}
|
|
88
|
+
if (!details.description) {
|
|
89
|
+
details.description = projectName
|
|
90
|
+
}
|
|
91
|
+
if (!details.id) {
|
|
92
|
+
details.id = projectName
|
|
93
|
+
}
|
|
94
|
+
if (!details.version) {
|
|
95
|
+
details.version = '1.0.0'
|
|
96
|
+
}
|
|
97
|
+
return details
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
async function _getMta(projectPath) {
|
|
101
|
+
// yaml.parse oesn't like null
|
|
102
|
+
const mtaFilePath = path.join(projectPath, MTA_YAML)
|
|
103
|
+
|
|
104
|
+
const existsMtaYaml = existsSync(mtaFilePath)
|
|
105
|
+
if (!existsMtaYaml) {
|
|
106
|
+
DEBUG?.('mta.yaml not existing')
|
|
107
|
+
return null
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const yamlStr = await fs.readFile(mtaFilePath, UTF_8)
|
|
111
|
+
|
|
112
|
+
// yaml returns null if string couldn't be parsed, e.g. empty string
|
|
113
|
+
return cds.parse.yaml(yamlStr)
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function _getApplicationName(mta, moduleName, moduleType) {
|
|
117
|
+
const module = _findModule(mta, moduleName, moduleType)
|
|
118
|
+
if (module) {
|
|
119
|
+
const appName = module.parameters && module.parameters['app-name']
|
|
120
|
+
return appName ? appName : module.name
|
|
121
|
+
}
|
|
122
|
+
return null
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
function _findModules(mta, moduleType) {
|
|
126
|
+
let modules = []
|
|
127
|
+
if (mta && Array.isArray(mta.modules)) {
|
|
128
|
+
modules = mta.modules.filter(module => module.type === moduleType)
|
|
129
|
+
}
|
|
130
|
+
return modules
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
function _findModule(mta, moduleName, moduleType) {
|
|
134
|
+
const modules = _findModules(mta, moduleType)
|
|
135
|
+
if (modules.length === 1) {
|
|
136
|
+
return modules[0]
|
|
137
|
+
} else if (modules.length > 1) {
|
|
138
|
+
return modules.find(module => typeof module.path === 'string' && module.path.includes(moduleName))
|
|
139
|
+
}
|
|
140
|
+
return null
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
function _findHdiResource(mta, moduleName) {
|
|
144
|
+
if (mta && Array.isArray(mta.resources)) {
|
|
145
|
+
const hdiResources = mta.resources.filter(resource => HDI_CONTAINER_TYPES.includes(resource.type))
|
|
146
|
+
|
|
147
|
+
if (hdiResources.length > 0) {
|
|
148
|
+
if (Array.isArray(mta.modules)) {
|
|
149
|
+
const module = _findModule(mta, moduleName, 'hdb')
|
|
150
|
+
if (module && Array.isArray(module.requires)) {
|
|
151
|
+
return hdiResources.find(hdiResource =>
|
|
152
|
+
module.requires.find(req =>
|
|
153
|
+
hdiResource.name === req.name
|
|
154
|
+
)
|
|
155
|
+
)
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
console.warn(`No matching hdi resource found for ${moduleName}. Using ${hdiResources[0].name}.`)
|
|
160
|
+
return hdiResources[0]
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
return null
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
module.exports = {
|
|
168
|
+
getHanaDbModuleDescriptor,
|
|
169
|
+
getServiceModuleDescriptor,
|
|
170
|
+
MTA_YAML
|
|
171
|
+
}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
|
|
2
1
|
const ParserContext = require("./parserContext");
|
|
3
2
|
const cdsDkVersion = require("../../../package.json").version;
|
|
4
3
|
|
|
@@ -29,4 +28,6 @@ function convertToCSN(context) {
|
|
|
29
28
|
return csn;
|
|
30
29
|
}
|
|
31
30
|
|
|
32
|
-
module.exports = {
|
|
31
|
+
module.exports = {
|
|
32
|
+
importAsyncAPI
|
|
33
|
+
}
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
const { importAsyncAPI } = require("./importAsyncAPI");
|
|
2
2
|
const { validateAsyncAPI } = require('./utils');
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
/**
|
|
5
|
+
* The starting function for conversion of AsyncAPI document to csn
|
|
6
|
+
* @returns AsyncAPI document
|
|
7
|
+
*/
|
|
5
8
|
function asyncapi2csn(source) {
|
|
6
|
-
//validate asyncapi document
|
|
9
|
+
// validate asyncapi document
|
|
7
10
|
const content = JSON.parse(source);
|
|
8
11
|
validateAsyncAPI(content);
|
|
9
12
|
|