@sap-ux/cf-deploy-config-writer 0.4.4 → 1.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/dist/cf-writer/app-config.d.ts +1 -1
- package/dist/cf-writer/app-config.js +72 -79
- package/dist/cf-writer/base-config.d.ts +1 -1
- package/dist/cf-writer/base-config.js +17 -23
- package/dist/cf-writer/cap-config.d.ts +1 -1
- package/dist/cf-writer/cap-config.js +21 -27
- package/dist/cf-writer/index.d.ts +3 -3
- package/dist/cf-writer/index.js +3 -9
- package/dist/constants.d.ts +5 -6
- package/dist/constants.js +70 -76
- package/dist/i18n.js +9 -19
- package/dist/index.d.ts +5 -4
- package/dist/index.js +4 -30
- package/dist/logger-helper.js +3 -6
- package/dist/mta-config/index.d.ts +3 -3
- package/dist/mta-config/index.js +64 -92
- package/dist/mta-config/mta.d.ts +1 -1
- package/dist/mta-config/mta.js +135 -141
- package/dist/mta-config/template-renderer.js +6 -9
- package/dist/mta-config/wait-for-mta.js +10 -13
- package/dist/types/index.d.ts +1 -1
- package/dist/types/index.js +8 -6
- package/dist/utils.d.ts +1 -1
- package/dist/utils.js +55 -74
- package/package.json +10 -8
package/dist/mta-config/mta.js
CHANGED
|
@@ -1,23 +1,18 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
const project_access_1 = require("@sap-ux/project-access");
|
|
13
|
-
const constants_1 = require("../constants");
|
|
14
|
-
const i18n_1 = require("../i18n");
|
|
15
|
-
const types_1 = require("../types");
|
|
16
|
-
const template_renderer_1 = require("./template-renderer");
|
|
1
|
+
import { format } from 'node:util';
|
|
2
|
+
import { dirname, join } from 'node:path';
|
|
3
|
+
import { existsSync, readFileSync, writeFileSync } from 'node:fs';
|
|
4
|
+
import { Mta } from '@sap/mta-lib';
|
|
5
|
+
import { isGenericODataDestination, isAbapEnvironmentOnBtp } from '@sap-ux/btp-utils';
|
|
6
|
+
import { YamlDocument } from '@sap-ux/yaml';
|
|
7
|
+
import { FileName, getMtaPath, hasDependency } from '@sap-ux/project-access';
|
|
8
|
+
import { CloudFoundry, RouterModule, DefaultMTADestination, SRV_API, ManagedXSUAA, MTABuildParams, MTABuildResult, DestinationServiceConfig, UI5ResourceDestination, UI5Destination, MTAAPIDestination, UI5StandaloneModuleDestination, ServiceAPIRequires, HTMLAppBuildParams, HTML5RepoHost, UI5AppfrontDestinationParameter, ManagedAppFront, CAPAppfrontDestination, deployMode, enableParallelDeployments, MAX_MTA_PREFIX_LENGTH, MAX_MTA_PREFIX_SHORT_LENGTH, MAX_MTA_PREFIX_SHORTER_LENGTH, MAX_ABAP_SERVICE_PREFIX_LENGTH, MAX_ABAP_SERVICE_NAME_LENGTH, MAX_MTA_ID_LENGTH } from '../constants.js';
|
|
9
|
+
import { t } from '../i18n.js';
|
|
10
|
+
import { CloudFoundryServiceType, RouterModuleType } from '../types/index.js';
|
|
11
|
+
import { renderTemplateToDisk } from './template-renderer.js';
|
|
17
12
|
/**
|
|
18
13
|
* A class representing interactions with the MTA binary, found at https://sap.github.io/cloud-mta-build-tool/.
|
|
19
14
|
*/
|
|
20
|
-
class MtaConfig {
|
|
15
|
+
export class MtaConfig {
|
|
21
16
|
mta;
|
|
22
17
|
apps = new Map();
|
|
23
18
|
modules = new Map();
|
|
@@ -45,7 +40,7 @@ class MtaConfig {
|
|
|
45
40
|
* @memberof Mta
|
|
46
41
|
*/
|
|
47
42
|
constructor(mtaDir, logger) {
|
|
48
|
-
this.mta = new
|
|
43
|
+
this.mta = new Mta(mtaDir, false);
|
|
49
44
|
this.log = logger;
|
|
50
45
|
this.mtaDir = mtaDir;
|
|
51
46
|
}
|
|
@@ -61,7 +56,7 @@ class MtaConfig {
|
|
|
61
56
|
this.mtaId = await this.mta?.getMtaID();
|
|
62
57
|
}
|
|
63
58
|
catch (error) {
|
|
64
|
-
this.log?.error(
|
|
59
|
+
this.log?.error(t('error.unableToLoadMTA', { error, mtaDir: this.mtaDir }));
|
|
65
60
|
}
|
|
66
61
|
return this;
|
|
67
62
|
}
|
|
@@ -85,16 +80,16 @@ class MtaConfig {
|
|
|
85
80
|
if (resource.parameters?.service) {
|
|
86
81
|
if (resource.parameters?.service === 'html5-apps-repo') {
|
|
87
82
|
this.resources.set(resource.parameters['service-plan'] === 'app-host'
|
|
88
|
-
?
|
|
83
|
+
? HTML5RepoHost
|
|
89
84
|
: 'html5-apps-repo:app-runtime', resource);
|
|
90
85
|
}
|
|
91
86
|
else if (resource.parameters?.service === 'xsuaa') {
|
|
92
|
-
this.resources.set(
|
|
87
|
+
this.resources.set(ManagedXSUAA, resource);
|
|
93
88
|
}
|
|
94
89
|
else if (resource.parameters?.service === 'app-front') {
|
|
95
|
-
this.resources.set(
|
|
90
|
+
this.resources.set(ManagedAppFront, resource);
|
|
96
91
|
}
|
|
97
|
-
else if (resource.type ===
|
|
92
|
+
else if (resource.type === CloudFoundryServiceType.Existing) {
|
|
98
93
|
this.resources.set(resource.name, resource);
|
|
99
94
|
}
|
|
100
95
|
else {
|
|
@@ -102,7 +97,7 @@ class MtaConfig {
|
|
|
102
97
|
}
|
|
103
98
|
}
|
|
104
99
|
});
|
|
105
|
-
this.log?.debug(
|
|
100
|
+
this.log?.debug(t('debug.mtaLoaded', { type: 'resources', size: this.resources.size }));
|
|
106
101
|
}
|
|
107
102
|
async loadMTAModules() {
|
|
108
103
|
const modules = (await this.mta?.getModules()) || [];
|
|
@@ -114,10 +109,10 @@ class MtaConfig {
|
|
|
114
109
|
else if (this.targetExists(module.requires ?? [], 'destination')) {
|
|
115
110
|
this.modules.set('com.sap.application.content:destination', module);
|
|
116
111
|
}
|
|
117
|
-
else if (this.targetExists(module.requires ?? [],
|
|
112
|
+
else if (this.targetExists(module.requires ?? [], HTML5RepoHost)) {
|
|
118
113
|
this.modules.set('com.sap.application.content:resource', module);
|
|
119
114
|
}
|
|
120
|
-
else if (this.targetExists(module.requires ?? [],
|
|
115
|
+
else if (this.targetExists(module.requires ?? [], ManagedAppFront)) {
|
|
121
116
|
this.modules.set('com.sap.application.content:appfront', module);
|
|
122
117
|
}
|
|
123
118
|
else {
|
|
@@ -125,17 +120,17 @@ class MtaConfig {
|
|
|
125
120
|
}
|
|
126
121
|
}
|
|
127
122
|
});
|
|
128
|
-
this.log?.debug(
|
|
123
|
+
this.log?.debug(t('debug.mtaLoaded', { type: 'modules', size: this.modules.size }));
|
|
129
124
|
}
|
|
130
125
|
async addAppContent() {
|
|
131
|
-
if (!this.resources.has(
|
|
126
|
+
if (!this.resources.has(HTML5RepoHost)) {
|
|
132
127
|
await this.addHtml5Host();
|
|
133
128
|
}
|
|
134
129
|
// Set up the basic module template, artifacts will be added in another step
|
|
135
|
-
const appHostName = this.resources.get(
|
|
130
|
+
const appHostName = this.resources.get(HTML5RepoHost)?.name;
|
|
136
131
|
if (appHostName) {
|
|
137
132
|
const appContentModule = {
|
|
138
|
-
name: `${this.prefix?.slice(0,
|
|
133
|
+
name: `${this.prefix?.slice(0, MAX_MTA_PREFIX_LENGTH)}-app-content`,
|
|
139
134
|
type: 'com.sap.application.content',
|
|
140
135
|
path: '.',
|
|
141
136
|
requires: [
|
|
@@ -158,15 +153,15 @@ class MtaConfig {
|
|
|
158
153
|
}
|
|
159
154
|
async addUaa() {
|
|
160
155
|
const resource = {
|
|
161
|
-
name: `${this.prefix?.slice(0,
|
|
156
|
+
name: `${this.prefix?.slice(0, MAX_MTA_PREFIX_LENGTH)}-uaa`,
|
|
162
157
|
type: 'org.cloudfoundry.managed-service',
|
|
163
158
|
parameters: {
|
|
164
159
|
service: 'xsuaa',
|
|
165
160
|
'service-plan': 'application',
|
|
166
161
|
path: './xs-security.json',
|
|
167
|
-
'service-name': `${this.prefix?.slice(0,
|
|
162
|
+
'service-name': `${this.prefix?.slice(0, MAX_MTA_PREFIX_LENGTH)}-xsuaa-service`,
|
|
168
163
|
config: {
|
|
169
|
-
xsappname: `${this.prefix?.slice(0,
|
|
164
|
+
xsappname: `${this.prefix?.slice(0, MAX_MTA_PREFIX_LENGTH)}` + '-${space-guid}',
|
|
170
165
|
'tenant-mode': 'dedicated'
|
|
171
166
|
}
|
|
172
167
|
}
|
|
@@ -177,7 +172,7 @@ class MtaConfig {
|
|
|
177
172
|
}
|
|
178
173
|
async addHtml5Runtime() {
|
|
179
174
|
const resource = {
|
|
180
|
-
name: `${this.prefix?.slice(0,
|
|
175
|
+
name: `${this.prefix?.slice(0, MAX_MTA_PREFIX_LENGTH)}-html5-repo-runtime`,
|
|
181
176
|
type: 'org.cloudfoundry.managed-service',
|
|
182
177
|
parameters: { 'service-plan': 'app-runtime', service: 'html5-apps-repo' }
|
|
183
178
|
};
|
|
@@ -196,7 +191,7 @@ class MtaConfig {
|
|
|
196
191
|
if (resource && !resource.parameters?.['service-name']) {
|
|
197
192
|
resource.parameters = {
|
|
198
193
|
...(resource.parameters ?? {}),
|
|
199
|
-
'service-name': `${this.prefix?.slice(0,
|
|
194
|
+
'service-name': `${this.prefix?.slice(0, MAX_MTA_PREFIX_LENGTH)}-${serviceName}-service`
|
|
200
195
|
};
|
|
201
196
|
await this.mta?.updateResource(resource);
|
|
202
197
|
this.resources.set(resourceName, resource);
|
|
@@ -223,31 +218,31 @@ class MtaConfig {
|
|
|
223
218
|
}
|
|
224
219
|
async addAppFrontResource() {
|
|
225
220
|
const resource = {
|
|
226
|
-
name: `${this.prefix?.slice(0,
|
|
221
|
+
name: `${this.prefix?.slice(0, MAX_MTA_PREFIX_SHORT_LENGTH)}-app-front`,
|
|
227
222
|
type: 'org.cloudfoundry.managed-service',
|
|
228
223
|
parameters: {
|
|
229
224
|
service: 'app-front',
|
|
230
|
-
'service-name': `${this.prefix?.slice(0,
|
|
225
|
+
'service-name': `${this.prefix?.slice(0, MAX_MTA_PREFIX_SHORTER_LENGTH)}-app-front-service`,
|
|
231
226
|
'service-plan': 'developer'
|
|
232
227
|
}
|
|
233
228
|
};
|
|
234
229
|
await this.mta?.addResource(resource);
|
|
235
|
-
this.resources.set(
|
|
230
|
+
this.resources.set(ManagedAppFront, resource);
|
|
236
231
|
this.dirty = true;
|
|
237
232
|
}
|
|
238
233
|
async addHtml5Host() {
|
|
239
|
-
const html5host = `${this.prefix?.slice(0,
|
|
234
|
+
const html5host = `${this.prefix?.slice(0, MAX_MTA_PREFIX_LENGTH)}-repo-host`; // Need to cater for -key being added too!
|
|
240
235
|
const resource = {
|
|
241
236
|
name: html5host,
|
|
242
237
|
type: 'org.cloudfoundry.managed-service',
|
|
243
238
|
parameters: {
|
|
244
|
-
'service-name': `${this.prefix?.slice(0,
|
|
239
|
+
'service-name': `${this.prefix?.slice(0, MAX_MTA_PREFIX_LENGTH)}-html5-service`,
|
|
245
240
|
'service-plan': 'app-host',
|
|
246
241
|
service: 'html5-apps-repo'
|
|
247
242
|
}
|
|
248
243
|
};
|
|
249
244
|
await this.mta?.addResource(resource);
|
|
250
|
-
this.resources.set(
|
|
245
|
+
this.resources.set(HTML5RepoHost, resource);
|
|
251
246
|
this.dirty = true;
|
|
252
247
|
}
|
|
253
248
|
/**
|
|
@@ -256,7 +251,7 @@ class MtaConfig {
|
|
|
256
251
|
* @param isManagedApp If the destination service is for a managed app (default: false)
|
|
257
252
|
*/
|
|
258
253
|
async addDestinationResource(isManagedApp = false) {
|
|
259
|
-
const destinationName = `${this.prefix?.slice(0,
|
|
254
|
+
const destinationName = `${this.prefix?.slice(0, MAX_MTA_PREFIX_LENGTH)}-destination-service`;
|
|
260
255
|
const resource = {
|
|
261
256
|
name: destinationName,
|
|
262
257
|
type: 'org.cloudfoundry.managed-service',
|
|
@@ -265,7 +260,7 @@ class MtaConfig {
|
|
|
265
260
|
'service-name': destinationName,
|
|
266
261
|
'service-plan': 'lite',
|
|
267
262
|
config: {
|
|
268
|
-
...
|
|
263
|
+
...DestinationServiceConfig.config,
|
|
269
264
|
['HTML5Runtime_enabled']: isManagedApp
|
|
270
265
|
}
|
|
271
266
|
}
|
|
@@ -294,12 +289,12 @@ class MtaConfig {
|
|
|
294
289
|
if (!resource.parameters?.config?.init_data?.instance?.destinations) {
|
|
295
290
|
resource.parameters.config = {
|
|
296
291
|
...resource.parameters.config,
|
|
297
|
-
...
|
|
292
|
+
...UI5ResourceDestination
|
|
298
293
|
};
|
|
299
294
|
}
|
|
300
295
|
// Append the UI5 destination if missing
|
|
301
|
-
if (!resource.parameters?.config?.init_data?.instance?.destinations?.some((destination) => destination.Name ===
|
|
302
|
-
resource.parameters.config.init_data.instance.destinations.push(
|
|
296
|
+
if (!resource.parameters?.config?.init_data?.instance?.destinations?.some((destination) => destination.Name === UI5Destination.Name)) {
|
|
297
|
+
resource.parameters.config.init_data.instance.destinations.push(UI5Destination);
|
|
303
298
|
}
|
|
304
299
|
await this.mta?.updateResource(resource);
|
|
305
300
|
this.resources.set('destination', resource);
|
|
@@ -313,12 +308,12 @@ class MtaConfig {
|
|
|
313
308
|
* @param supportedResource Selected resource to be added (default: ManagedXSUAA)
|
|
314
309
|
* @param appendSrvApi If `srv-api` should be appended, typically used for CAP flows (default: true)
|
|
315
310
|
*/
|
|
316
|
-
async updateServerModule(moduleType, supportedResource =
|
|
311
|
+
async updateServerModule(moduleType, supportedResource = ManagedXSUAA, appendSrvApi = true) {
|
|
317
312
|
const mtaResource = this.resources.get(supportedResource);
|
|
318
313
|
const serverModule = this.modules.get(moduleType);
|
|
319
314
|
if (serverModule) {
|
|
320
|
-
if (appendSrvApi && !serverModule.provides?.some((ele) => ele.name ===
|
|
321
|
-
serverModule.provides = [...(serverModule.provides ?? []), ...[
|
|
315
|
+
if (appendSrvApi && !serverModule.provides?.some((ele) => ele.name === SRV_API)) {
|
|
316
|
+
serverModule.provides = [...(serverModule.provides ?? []), ...[ServiceAPIRequires]];
|
|
322
317
|
}
|
|
323
318
|
if (mtaResource && !serverModule.requires?.some((ele) => ele.name === mtaResource.name)) {
|
|
324
319
|
serverModule.requires = [...(serverModule.requires ?? []), ...[{ name: mtaResource.name }]];
|
|
@@ -334,19 +329,19 @@ class MtaConfig {
|
|
|
334
329
|
* @private
|
|
335
330
|
*/
|
|
336
331
|
async addManagedUAAWithSecurity() {
|
|
337
|
-
this.log?.debug(
|
|
332
|
+
this.log?.debug(t('debug.addXsuaaService'));
|
|
338
333
|
const resource = {
|
|
339
|
-
name: `${this.prefix?.slice(0,
|
|
334
|
+
name: `${this.prefix?.slice(0, MAX_MTA_PREFIX_LENGTH)}-uaa`,
|
|
340
335
|
type: 'org.cloudfoundry.managed-service',
|
|
341
336
|
parameters: {
|
|
342
337
|
path: './xs-security.json',
|
|
343
338
|
service: 'xsuaa',
|
|
344
|
-
'service-name': `${this.prefix?.slice(0,
|
|
339
|
+
'service-name': `${this.prefix?.slice(0, MAX_MTA_PREFIX_LENGTH)}-xsuaa-service`,
|
|
345
340
|
'service-plan': 'application',
|
|
346
341
|
...(this.modules.has('nodejs') && this.modules.has('com.sap.application.content:appfront')
|
|
347
342
|
? {
|
|
348
343
|
config: {
|
|
349
|
-
xsappname: `${this.prefix?.slice(0,
|
|
344
|
+
xsappname: `${this.prefix?.slice(0, MAX_MTA_PREFIX_LENGTH)}-\${org}-\${space}`,
|
|
350
345
|
'tenant-mode': 'dedicated'
|
|
351
346
|
}
|
|
352
347
|
}
|
|
@@ -354,7 +349,7 @@ class MtaConfig {
|
|
|
354
349
|
}
|
|
355
350
|
};
|
|
356
351
|
await this.mta?.addResource(resource);
|
|
357
|
-
this.resources.set(
|
|
352
|
+
this.resources.set(ManagedXSUAA, resource);
|
|
358
353
|
this.dirty = true;
|
|
359
354
|
}
|
|
360
355
|
/**
|
|
@@ -364,7 +359,7 @@ class MtaConfig {
|
|
|
364
359
|
* @returns True if the destination is an OData destination (ODATA_GENERIC or ODATA_ABAP), false otherwise
|
|
365
360
|
*/
|
|
366
361
|
isODataDestination(destination) {
|
|
367
|
-
return
|
|
362
|
+
return isGenericODataDestination(destination) || isAbapEnvironmentOnBtp(destination);
|
|
368
363
|
}
|
|
369
364
|
/**
|
|
370
365
|
* Cleanup missing content for Managed | Standalone router types.
|
|
@@ -372,7 +367,7 @@ class MtaConfig {
|
|
|
372
367
|
* @private
|
|
373
368
|
*/
|
|
374
369
|
async cleanupMissingResources() {
|
|
375
|
-
this.log?.debug(
|
|
370
|
+
this.log?.debug(t('debug.addMissingModules'));
|
|
376
371
|
if (!this.modules.has('com.sap.application.content:appfront')) {
|
|
377
372
|
if (!this.modules.has('com.sap.application.content:resource')) {
|
|
378
373
|
await this.addAppContent();
|
|
@@ -389,19 +384,19 @@ class MtaConfig {
|
|
|
389
384
|
}
|
|
390
385
|
}
|
|
391
386
|
async cleanupModules() {
|
|
392
|
-
this.log?.debug(
|
|
387
|
+
this.log?.debug(t('debug.cleanupModules'));
|
|
393
388
|
// Handle standalone | managed
|
|
394
389
|
for (const module of [
|
|
395
390
|
this.modules.get('com.sap.application.content:destination'),
|
|
396
391
|
this.modules.get('approuter.nodejs')
|
|
397
392
|
].filter((elem) => elem !== undefined)) {
|
|
398
393
|
const destinationName = this.resources.get('destination')?.name ??
|
|
399
|
-
`${this.prefix?.slice(0,
|
|
394
|
+
`${this.prefix?.slice(0, MAX_MTA_PREFIX_LENGTH)}-destination-service`;
|
|
400
395
|
if (module?.requires?.findIndex((app) => app.name === destinationName) === -1) {
|
|
401
396
|
if (module.type === 'approuter.nodejs') {
|
|
402
397
|
module.requires.push({
|
|
403
398
|
name: destinationName,
|
|
404
|
-
...
|
|
399
|
+
...UI5StandaloneModuleDestination
|
|
405
400
|
});
|
|
406
401
|
}
|
|
407
402
|
if (module.type === 'com.sap.application.content') {
|
|
@@ -505,21 +500,21 @@ class MtaConfig {
|
|
|
505
500
|
const contentModule = this.getAppContentModule();
|
|
506
501
|
let isHTML5AlreadyExisting = false; // False by default
|
|
507
502
|
if (contentModule) {
|
|
508
|
-
contentModule[
|
|
509
|
-
contentModule[
|
|
510
|
-
contentModule[
|
|
511
|
-
contentModule[
|
|
503
|
+
contentModule[MTABuildParams] = contentModule[MTABuildParams] ?? {};
|
|
504
|
+
contentModule[MTABuildParams][MTABuildResult] =
|
|
505
|
+
contentModule[MTABuildParams]?.[MTABuildResult] ?? `resources`; // Default
|
|
506
|
+
contentModule[MTABuildParams].requires = contentModule[MTABuildParams].requires ?? [];
|
|
512
507
|
const artifactName = `${appName}.zip`;
|
|
513
508
|
// The name of the HTML5 app will always be the artifact name
|
|
514
|
-
if (contentModule[
|
|
515
|
-
this.log?.debug(
|
|
509
|
+
if (contentModule[MTABuildParams].requires?.findIndex((app) => app.artifacts?.includes?.(artifactName)) !== -1) {
|
|
510
|
+
this.log?.debug(t('debug.html5AlreadyExists', { appName }));
|
|
516
511
|
isHTML5AlreadyExisting = true;
|
|
517
512
|
}
|
|
518
513
|
else {
|
|
519
|
-
contentModule[
|
|
520
|
-
name: appName.slice(0,
|
|
514
|
+
contentModule[MTABuildParams].requires.push({
|
|
515
|
+
name: appName.slice(0, MAX_MTA_ID_LENGTH),
|
|
521
516
|
artifacts: [artifactName],
|
|
522
|
-
'target-path': `${contentModule[
|
|
517
|
+
'target-path': `${contentModule[MTABuildParams][MTABuildResult]}/`.replace(/\/{2,}/g, '/') // Matches two or more consecutive slashes where at least 2 repetitions of /
|
|
523
518
|
});
|
|
524
519
|
}
|
|
525
520
|
await this.mta?.updateModule(contentModule);
|
|
@@ -528,15 +523,15 @@ class MtaConfig {
|
|
|
528
523
|
// Add application module, if not found already
|
|
529
524
|
if (!isHTML5AlreadyExisting && !this.apps.get(appName)) {
|
|
530
525
|
const app = {
|
|
531
|
-
name: appName.slice(0,
|
|
526
|
+
name: appName.slice(0, MAX_MTA_ID_LENGTH),
|
|
532
527
|
type: 'html5',
|
|
533
528
|
path: appPath,
|
|
534
|
-
'build-parameters':
|
|
529
|
+
'build-parameters': HTMLAppBuildParams
|
|
535
530
|
};
|
|
536
531
|
await this.mta?.addModule(app);
|
|
537
532
|
this.apps.set(appName, app);
|
|
538
533
|
this.dirty = true;
|
|
539
|
-
this.log?.debug(
|
|
534
|
+
this.log?.debug(t('debug.html5AppAdded', { appName }));
|
|
540
535
|
}
|
|
541
536
|
await this.syncHtml5Apps();
|
|
542
537
|
await this.addMtaDeployParameters();
|
|
@@ -545,18 +540,18 @@ class MtaConfig {
|
|
|
545
540
|
// Need to handle where existing HTML5 apps are added by `cds` which follow a different naming convention when added to mta
|
|
546
541
|
for (const [appName, app] of this.apps.entries()) {
|
|
547
542
|
if (app.type === 'html5' && app.path && app['build-parameters']) {
|
|
548
|
-
this.log?.debug(
|
|
543
|
+
this.log?.debug(t('debug.processHTML5App', { appName }));
|
|
549
544
|
try {
|
|
550
545
|
// Supported apps will have a dependency on`@sap/ux-ui5-tooling`, assume it's a UI5 app managed by our tooling
|
|
551
|
-
const packageJson = JSON.parse(
|
|
552
|
-
if (packageJson &&
|
|
546
|
+
const packageJson = JSON.parse(readFileSync(join(this.mtaDir, app.path, FileName.Package), 'utf8'));
|
|
547
|
+
if (packageJson && hasDependency(packageJson, '@sap/ux-ui5-tooling')) {
|
|
553
548
|
app['build-parameters'].commands = ['npm install', 'npm run build:cf'];
|
|
554
549
|
await this.mta?.updateModule(app);
|
|
555
550
|
this.dirty = true;
|
|
556
551
|
}
|
|
557
552
|
}
|
|
558
553
|
catch (error) {
|
|
559
|
-
this.log?.debug(
|
|
554
|
+
this.log?.debug(t('debug.unableToReadPackageJson', { error }));
|
|
560
555
|
}
|
|
561
556
|
}
|
|
562
557
|
}
|
|
@@ -568,8 +563,8 @@ class MtaConfig {
|
|
|
568
563
|
*/
|
|
569
564
|
async addConnectivityResource() {
|
|
570
565
|
const serviceType = 'connectivity';
|
|
571
|
-
const resourceType =
|
|
572
|
-
const resourceName = `${this.prefix?.slice(0,
|
|
566
|
+
const resourceType = CloudFoundryServiceType.Managed;
|
|
567
|
+
const resourceName = `${this.prefix?.slice(0, MAX_MTA_PREFIX_LENGTH)}-connectivity`;
|
|
573
568
|
const router = this.modules.get('approuter.nodejs');
|
|
574
569
|
if (router) {
|
|
575
570
|
if (router.requires?.findIndex((resource) => resource.name === resourceName) === -1) {
|
|
@@ -601,16 +596,16 @@ class MtaConfig {
|
|
|
601
596
|
* @returns {Promise<void>} - A promise that resolves when the change request has been processed.
|
|
602
597
|
*/
|
|
603
598
|
async addRouterType({ routerType, addMissingModules = true } = {}) {
|
|
604
|
-
if (routerType ===
|
|
599
|
+
if (routerType === RouterModuleType.Standard) {
|
|
605
600
|
await this.addStandaloneRouter(true);
|
|
606
601
|
}
|
|
607
|
-
if (routerType ===
|
|
602
|
+
if (routerType === RouterModuleType.Managed) {
|
|
608
603
|
await this.addManagedAppRouter();
|
|
609
604
|
}
|
|
610
|
-
if (routerType ===
|
|
605
|
+
if (routerType === RouterModuleType.AppFront) {
|
|
611
606
|
await this.addAppFrontAppRouter();
|
|
612
607
|
}
|
|
613
|
-
if (routerType !==
|
|
608
|
+
if (routerType !== RouterModuleType.AppFront) {
|
|
614
609
|
if (addMissingModules) {
|
|
615
610
|
await this.cleanupMissingResources();
|
|
616
611
|
}
|
|
@@ -650,7 +645,7 @@ class MtaConfig {
|
|
|
650
645
|
* @returns {Promise<void>} A promise that resolves when the change request has been processed.
|
|
651
646
|
*/
|
|
652
647
|
async addAbapService(serviceName, btpService) {
|
|
653
|
-
const newResourceName = `${this.prefix?.slice(0,
|
|
648
|
+
const newResourceName = `${this.prefix?.slice(0, MAX_ABAP_SERVICE_PREFIX_LENGTH)}-abap-${serviceName.slice(0, MAX_ABAP_SERVICE_NAME_LENGTH)}`;
|
|
654
649
|
const router = this.modules.get('approuter.nodejs');
|
|
655
650
|
if (router) {
|
|
656
651
|
if (router.requires?.findIndex((resource) => resource.name === newResourceName) === -1) {
|
|
@@ -660,7 +655,7 @@ class MtaConfig {
|
|
|
660
655
|
}
|
|
661
656
|
const abapServiceResource = {
|
|
662
657
|
name: newResourceName,
|
|
663
|
-
type:
|
|
658
|
+
type: CloudFoundryServiceType.Existing,
|
|
664
659
|
parameters: {
|
|
665
660
|
'service-name': serviceName,
|
|
666
661
|
protocol: ['ODataV2'],
|
|
@@ -697,7 +692,7 @@ class MtaConfig {
|
|
|
697
692
|
* @returns {Promise<void>} A promise that resolves when the change request has been processed.
|
|
698
693
|
*/
|
|
699
694
|
async addStandaloneRouter(fromServerGenerator = false) {
|
|
700
|
-
this.log?.debug(
|
|
695
|
+
this.log?.debug(t('debug.addingRouter', { routerType: RouterModuleType.Standard }));
|
|
701
696
|
if (!this.resources.has('xsuaa')) {
|
|
702
697
|
await this.addUaa();
|
|
703
698
|
}
|
|
@@ -712,9 +707,9 @@ class MtaConfig {
|
|
|
712
707
|
const destinationName = this.resources.get('destination')?.name;
|
|
713
708
|
if (destinationName && xsuaaName && appRuntimeName) {
|
|
714
709
|
const router = {
|
|
715
|
-
name: `${this.prefix?.slice(0,
|
|
710
|
+
name: `${this.prefix?.slice(0, MAX_MTA_PREFIX_LENGTH)}-router`,
|
|
716
711
|
type: 'approuter.nodejs',
|
|
717
|
-
path: fromServerGenerator ? `${
|
|
712
|
+
path: fromServerGenerator ? `${RouterModule}` : `${CloudFoundry}/${RouterModule}`,
|
|
718
713
|
parameters: {
|
|
719
714
|
'disk-quota': '256M',
|
|
720
715
|
memory: '256M'
|
|
@@ -740,7 +735,7 @@ class MtaConfig {
|
|
|
740
735
|
* @returns {boolean} true if the mta contains an XSUAA resource
|
|
741
736
|
*/
|
|
742
737
|
hasManagedXsuaaResource() {
|
|
743
|
-
return this.resources.has(
|
|
738
|
+
return this.resources.has(ManagedXSUAA);
|
|
744
739
|
}
|
|
745
740
|
/**
|
|
746
741
|
* Add an mta extension config, either creating a new mtaext file or extending an existing one.
|
|
@@ -765,19 +760,19 @@ class MtaConfig {
|
|
|
765
760
|
*/
|
|
766
761
|
let destinationServiceName = this.resources.get('destination')?.name;
|
|
767
762
|
if (!destinationServiceName) {
|
|
768
|
-
this.log?.info(
|
|
769
|
-
destinationServiceName = `${this.prefix?.slice(0,
|
|
763
|
+
this.log?.info(t('info.existingDestinationNotFound'));
|
|
764
|
+
destinationServiceName = `${this.prefix?.slice(0, MAX_MTA_PREFIX_LENGTH)}-destination-service`;
|
|
770
765
|
}
|
|
771
766
|
const appMtaId = this.mtaId;
|
|
772
|
-
const mtaExtFilePath =
|
|
767
|
+
const mtaExtFilePath = join(this.mta.mtaDirPath, FileName.MtaExtYaml);
|
|
773
768
|
let mtaExtensionYamlFile;
|
|
774
769
|
try {
|
|
775
|
-
const mtaExtContents =
|
|
776
|
-
mtaExtensionYamlFile = await
|
|
770
|
+
const mtaExtContents = readFileSync(mtaExtFilePath, 'utf-8');
|
|
771
|
+
mtaExtensionYamlFile = await YamlDocument.newInstance(mtaExtContents);
|
|
777
772
|
}
|
|
778
773
|
catch (err) {
|
|
779
774
|
// File does not exist or cannot be parsed, either way we create a new one
|
|
780
|
-
this.log?.info(
|
|
775
|
+
this.log?.info(t('info.existingMTAExtensionNotFound', { error: err.message }));
|
|
781
776
|
}
|
|
782
777
|
// Create a new mta extension file
|
|
783
778
|
if (!mtaExtensionYamlFile) {
|
|
@@ -791,8 +786,8 @@ class MtaConfig {
|
|
|
791
786
|
destinationServiceName: destinationServiceName,
|
|
792
787
|
mtaVersion: '1.0.0'
|
|
793
788
|
};
|
|
794
|
-
|
|
795
|
-
this.log?.info(
|
|
789
|
+
renderTemplateToDisk(`app/${FileName.MtaExtYaml}`, mtaExtFilePath, mtaExt);
|
|
790
|
+
this.log?.info(t('info.mtaExtensionCreated', { appMtaId, mtaExtFile: FileName.MtaExtYaml }));
|
|
796
791
|
}
|
|
797
792
|
else {
|
|
798
793
|
// Create an entry in an existing mta extension file
|
|
@@ -813,11 +808,11 @@ class MtaConfig {
|
|
|
813
808
|
path: `resources.${resIdx}.parameters.config.init_data.instance.destinations`,
|
|
814
809
|
value: nodeToInsert
|
|
815
810
|
});
|
|
816
|
-
|
|
817
|
-
this.log?.info(
|
|
811
|
+
writeFileSync(mtaExtFilePath, mtaExtensionYamlFile.toString());
|
|
812
|
+
this.log?.info(t('info.mtaExtensionUpdated', { mtaExtFile: FileName.MtaExtYaml }));
|
|
818
813
|
}
|
|
819
814
|
else {
|
|
820
|
-
this.log?.error(
|
|
815
|
+
this.log?.error(t('error.updatingMTAExtensionFailed', { mtaExtFilePath }));
|
|
821
816
|
}
|
|
822
817
|
}
|
|
823
818
|
}
|
|
@@ -845,11 +840,11 @@ class MtaConfig {
|
|
|
845
840
|
const module = this.modules.get('com.sap.application.content:appfront');
|
|
846
841
|
if (module) {
|
|
847
842
|
// If the destination provided is `fiori-default-srv-api` then use the default destination name
|
|
848
|
-
const destName = cfDestination ===
|
|
843
|
+
const destName = cfDestination === DefaultMTADestination ? SRV_API : cfDestination;
|
|
849
844
|
// Ensure the destination does not exist already!
|
|
850
845
|
if (!module.parameters?.config?.destinations?.some((destination) => destination.Name === destName)) {
|
|
851
846
|
const destination = {
|
|
852
|
-
...
|
|
847
|
+
...CAPAppfrontDestination,
|
|
853
848
|
name: destName
|
|
854
849
|
};
|
|
855
850
|
module.parameters?.config?.destinations.push(destination);
|
|
@@ -866,26 +861,26 @@ class MtaConfig {
|
|
|
866
861
|
async appendInstanceBasedDestination(cfDestination) {
|
|
867
862
|
// Part 1. Update the destination service with the new instance based destination
|
|
868
863
|
const destinationResource = this.resources.get('destination');
|
|
869
|
-
const capDestName = cfDestination ===
|
|
864
|
+
const capDestName = cfDestination === DefaultMTADestination ? SRV_API : cfDestination;
|
|
870
865
|
if (destinationResource) {
|
|
871
|
-
if (!destinationResource.requires?.some((ele) => ele.name ===
|
|
866
|
+
if (!destinationResource.requires?.some((ele) => ele.name === SRV_API)) {
|
|
872
867
|
destinationResource.requires = [
|
|
873
868
|
...(destinationResource.requires ?? []),
|
|
874
869
|
...[
|
|
875
870
|
{
|
|
876
|
-
name:
|
|
871
|
+
name: SRV_API
|
|
877
872
|
}
|
|
878
873
|
]
|
|
879
874
|
];
|
|
880
875
|
}
|
|
881
876
|
// Part 2. Only append the default destination if it does not exist already
|
|
882
|
-
const isSrvApiExisting = cfDestination ===
|
|
883
|
-
destinationResource.parameters?.config?.init_data?.instance?.destinations?.some((destination) => destination.Name ===
|
|
877
|
+
const isSrvApiExisting = cfDestination === SRV_API &&
|
|
878
|
+
destinationResource.parameters?.config?.init_data?.instance?.destinations?.some((destination) => destination.Name === SRV_API);
|
|
884
879
|
// Part 3. If the destination is not already existing, append it
|
|
885
880
|
if (!isSrvApiExisting) {
|
|
886
881
|
if (!destinationResource.parameters?.config?.init_data?.instance?.destinations?.some((destination) => destination.Name === capDestName)) {
|
|
887
882
|
destinationResource.parameters?.config?.init_data?.instance?.destinations?.push({
|
|
888
|
-
...
|
|
883
|
+
...MTAAPIDestination,
|
|
889
884
|
Name: capDestName
|
|
890
885
|
});
|
|
891
886
|
}
|
|
@@ -912,19 +907,19 @@ class MtaConfig {
|
|
|
912
907
|
* Add an App Router to the MTA.
|
|
913
908
|
*/
|
|
914
909
|
async addAppFrontAppRouter() {
|
|
915
|
-
if (!this.resources.has(
|
|
910
|
+
if (!this.resources.has(ManagedXSUAA)) {
|
|
916
911
|
await this.addManagedUAAWithSecurity();
|
|
917
912
|
}
|
|
918
|
-
await this.updateServiceName('xsuaa',
|
|
919
|
-
if (!this.resources.has(
|
|
913
|
+
await this.updateServiceName('xsuaa', ManagedXSUAA);
|
|
914
|
+
if (!this.resources.has(ManagedAppFront)) {
|
|
920
915
|
await this.addAppFrontResource();
|
|
921
916
|
}
|
|
922
917
|
if (!this.modules.has('com.sap.application.content:appfront')) {
|
|
923
|
-
this.log?.debug(
|
|
924
|
-
const appHostName = this.resources.get(
|
|
918
|
+
this.log?.debug(t('debug.addingRouter', { routerType: RouterModuleType.AppFront }));
|
|
919
|
+
const appHostName = this.resources.get(ManagedAppFront)?.name;
|
|
925
920
|
if (appHostName) {
|
|
926
921
|
const appContentModule = {
|
|
927
|
-
name: `${this.prefix?.slice(0,
|
|
922
|
+
name: `${this.prefix?.slice(0, MAX_MTA_PREFIX_LENGTH)}-app-content`,
|
|
928
923
|
type: 'com.sap.application.content',
|
|
929
924
|
path: '.',
|
|
930
925
|
requires: [
|
|
@@ -937,13 +932,13 @@ class MtaConfig {
|
|
|
937
932
|
],
|
|
938
933
|
parameters: {
|
|
939
934
|
config: {
|
|
940
|
-
destinations: [
|
|
935
|
+
destinations: [UI5AppfrontDestinationParameter]
|
|
941
936
|
}
|
|
942
937
|
}
|
|
943
938
|
};
|
|
944
939
|
// Append missing requires if CAP is found
|
|
945
940
|
if (this.modules.has('nodejs')) {
|
|
946
|
-
appContentModule.requires?.push({ name:
|
|
941
|
+
appContentModule.requires?.push({ name: SRV_API });
|
|
947
942
|
}
|
|
948
943
|
await this.mta?.addModule(appContentModule);
|
|
949
944
|
this.modules.set('com.sap.application.content:appfront', appContentModule);
|
|
@@ -951,8 +946,8 @@ class MtaConfig {
|
|
|
951
946
|
}
|
|
952
947
|
}
|
|
953
948
|
// Append resources
|
|
954
|
-
await this.updateServerModule('com.sap.application.content:appfront',
|
|
955
|
-
await this.updateServerModule('nodejs',
|
|
949
|
+
await this.updateServerModule('com.sap.application.content:appfront', ManagedXSUAA, false);
|
|
950
|
+
await this.updateServerModule('nodejs', ManagedXSUAA, false);
|
|
956
951
|
}
|
|
957
952
|
/**
|
|
958
953
|
* Add a managed app router to the MTA.
|
|
@@ -963,27 +958,27 @@ class MtaConfig {
|
|
|
963
958
|
if (!this.resources.has('destination')) {
|
|
964
959
|
await this.addDestinationResource(true);
|
|
965
960
|
}
|
|
966
|
-
if (!this.resources.has(
|
|
961
|
+
if (!this.resources.has(ManagedXSUAA)) {
|
|
967
962
|
await this.addManagedUAAWithSecurity();
|
|
968
963
|
}
|
|
969
|
-
if (!this.resources.has(
|
|
964
|
+
if (!this.resources.has(HTML5RepoHost)) {
|
|
970
965
|
await this.addHtml5Host();
|
|
971
966
|
}
|
|
972
967
|
// We only want to append a new one, if missing from the existing mta config
|
|
973
968
|
if (!this.modules.has('com.sap.application.content:destination')) {
|
|
974
|
-
this.log?.debug(
|
|
969
|
+
this.log?.debug(t('debug.addingRouter', { routerType: RouterModuleType.Managed }));
|
|
975
970
|
const destinationName = this.resources.get('destination')?.name;
|
|
976
|
-
const appHostName = this.resources.get(
|
|
977
|
-
const managedXSUAAName = this.resources.get(
|
|
971
|
+
const appHostName = this.resources.get(HTML5RepoHost)?.name;
|
|
972
|
+
const managedXSUAAName = this.resources.get(ManagedXSUAA)?.name;
|
|
978
973
|
if (destinationName && appHostName && managedXSUAAName) {
|
|
979
974
|
// Align the service-name, not always present
|
|
980
|
-
await this.updateServiceName('html5',
|
|
981
|
-
await this.updateServiceName('xsuaa',
|
|
975
|
+
await this.updateServiceName('html5', HTML5RepoHost);
|
|
976
|
+
await this.updateServiceName('xsuaa', ManagedXSUAA);
|
|
982
977
|
// Retrieve the service-name
|
|
983
|
-
const appHostServiceName = this.getServiceInstanceName(
|
|
984
|
-
const managedXSUAAServiceName = this.getServiceInstanceName(
|
|
978
|
+
const appHostServiceName = this.getServiceInstanceName(HTML5RepoHost);
|
|
979
|
+
const managedXSUAAServiceName = this.getServiceInstanceName(ManagedXSUAA);
|
|
985
980
|
const router = {
|
|
986
|
-
name: `${this.prefix?.slice(0,
|
|
981
|
+
name: `${this.prefix?.slice(0, MAX_MTA_PREFIX_LENGTH)}-destination-content`,
|
|
987
982
|
type: 'com.sap.application.content',
|
|
988
983
|
requires: [
|
|
989
984
|
{
|
|
@@ -1014,17 +1009,17 @@ class MtaConfig {
|
|
|
1014
1009
|
instance: {
|
|
1015
1010
|
destinations: [
|
|
1016
1011
|
{
|
|
1017
|
-
Name: `${this.prefix?.slice(0,
|
|
1012
|
+
Name: `${this.prefix?.slice(0, MAX_MTA_PREFIX_LENGTH)}_html_repo_host`,
|
|
1018
1013
|
ServiceInstanceName: appHostServiceName,
|
|
1019
1014
|
ServiceKeyName: `${appHostName}-key`,
|
|
1020
|
-
'sap.cloud.service': `${this.prefix?.slice(0,
|
|
1015
|
+
'sap.cloud.service': `${this.prefix?.slice(0, MAX_MTA_PREFIX_LENGTH)}`
|
|
1021
1016
|
},
|
|
1022
1017
|
{
|
|
1023
1018
|
Authentication: 'OAuth2UserTokenExchange',
|
|
1024
|
-
Name: `${this.prefix?.slice(0,
|
|
1019
|
+
Name: `${this.prefix?.slice(0, MAX_MTA_PREFIX_LENGTH)}_uaa`,
|
|
1025
1020
|
ServiceInstanceName: managedXSUAAServiceName,
|
|
1026
1021
|
ServiceKeyName: `${managedXSUAAName}-key`,
|
|
1027
|
-
'sap.cloud.service': `${this.prefix?.slice(0,
|
|
1022
|
+
'sap.cloud.service': `${this.prefix?.slice(0, MAX_MTA_PREFIX_LENGTH)}`
|
|
1028
1023
|
}
|
|
1029
1024
|
],
|
|
1030
1025
|
'existing_destinations_policy': 'update'
|
|
@@ -1072,7 +1067,7 @@ class MtaConfig {
|
|
|
1072
1067
|
* @returns {string} return a formatted prefix value.
|
|
1073
1068
|
*/
|
|
1074
1069
|
getFormattedPrefix(formatString) {
|
|
1075
|
-
return
|
|
1070
|
+
return format(formatString, this.prefix).replace(/[^\w-]/g, '_');
|
|
1076
1071
|
}
|
|
1077
1072
|
/**
|
|
1078
1073
|
* Retrieve the app-content module, different types can be found depending on the router type configuration.
|
|
@@ -1104,20 +1099,19 @@ class MtaConfig {
|
|
|
1104
1099
|
async addMtaDeployParameters() {
|
|
1105
1100
|
let params = await this.getParameters();
|
|
1106
1101
|
params = { ...(params ?? {}), ...{} };
|
|
1107
|
-
params[
|
|
1108
|
-
params[
|
|
1102
|
+
params[deployMode] = 'html5-repo';
|
|
1103
|
+
params[enableParallelDeployments] = true;
|
|
1109
1104
|
await this.updateParameters(params);
|
|
1110
1105
|
}
|
|
1111
1106
|
}
|
|
1112
|
-
exports.MtaConfig = MtaConfig;
|
|
1113
1107
|
/**
|
|
1114
1108
|
* Returns true if there's an MTA configuration file in the supplied directory.
|
|
1115
1109
|
*
|
|
1116
1110
|
* @param {string} dir directory to check for MTA configuration file
|
|
1117
1111
|
* @returns {boolean} true | false if MTA configuration file is found
|
|
1118
1112
|
*/
|
|
1119
|
-
function isMTAFound(dir) {
|
|
1120
|
-
return
|
|
1113
|
+
export function isMTAFound(dir) {
|
|
1114
|
+
return existsSync(join(dir, FileName.MtaYaml));
|
|
1121
1115
|
}
|
|
1122
1116
|
/**
|
|
1123
1117
|
* Returns true if there's an MTA configuration file in the supplied directory and contains an ABAP service binding.
|
|
@@ -1128,17 +1122,17 @@ function isMTAFound(dir) {
|
|
|
1128
1122
|
* @param {Logger} logger - option logger instance
|
|
1129
1123
|
* @returns {boolean} true if mta.yaml is found and ABAP service binding is found
|
|
1130
1124
|
*/
|
|
1131
|
-
async function useAbapDirectServiceBinding(appPath, findMtaPath, mtaPath = '', logger) {
|
|
1125
|
+
export async function useAbapDirectServiceBinding(appPath, findMtaPath, mtaPath = '', logger) {
|
|
1132
1126
|
try {
|
|
1133
1127
|
let rootPath;
|
|
1134
1128
|
if (findMtaPath) {
|
|
1135
|
-
const foundMtaPath = await
|
|
1129
|
+
const foundMtaPath = await getMtaPath(appPath);
|
|
1136
1130
|
if (foundMtaPath) {
|
|
1137
|
-
rootPath =
|
|
1131
|
+
rootPath = dirname(foundMtaPath.mtaPath);
|
|
1138
1132
|
}
|
|
1139
1133
|
}
|
|
1140
1134
|
else if (mtaPath) {
|
|
1141
|
-
rootPath =
|
|
1135
|
+
rootPath = dirname(mtaPath);
|
|
1142
1136
|
}
|
|
1143
1137
|
if (rootPath) {
|
|
1144
1138
|
const mtaConfig = await MtaConfig.newInstance(rootPath, logger);
|
|
@@ -1149,7 +1143,7 @@ async function useAbapDirectServiceBinding(appPath, findMtaPath, mtaPath = '', l
|
|
|
1149
1143
|
}
|
|
1150
1144
|
}
|
|
1151
1145
|
catch (error) {
|
|
1152
|
-
logger?.debug(
|
|
1146
|
+
logger?.debug(t('debug.logError', { error, method: 'useAbapDirectServiceBinding' }));
|
|
1153
1147
|
return false;
|
|
1154
1148
|
}
|
|
1155
1149
|
}
|