@ui5/task-adaptation 1.6.6 → 1.6.8
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/CHANGELOG.md +9 -1
- package/dist/adapters/abapAdapter.d.ts +2 -1
- package/dist/adapters/abapAdapter.js +3 -0
- package/dist/adapters/adapter.d.ts +2 -1
- package/dist/adapters/cfAdapter.d.ts +2 -1
- package/dist/adapters/cfAdapter.js +14 -0
- package/dist/adapters/commands/command.d.ts +7 -7
- package/dist/adapters/commands/command.js +3 -2
- package/dist/adapters/commands/downloadAnnotationsCommand.d.ts +1 -1
- package/dist/adapters/commands/downloadAnnotationsCommand.js +4 -3
- package/dist/adapters/commands/fetchPreviewResourcesCommand.js +4 -2
- package/dist/adapters/commands/filterFilesCommand.d.ts +1 -1
- package/dist/adapters/commands/filterFilesCommand.js +2 -1
- package/dist/adapters/commands/i18nPropertiesMergeCommand.d.ts +1 -1
- package/dist/adapters/commands/i18nPropertiesMergeCommand.js +9 -6
- package/dist/adapters/commands/omitDeletedResourcesCommand.d.ts +1 -1
- package/dist/adapters/commands/omitDeletedResourcesCommand.js +1 -1
- package/dist/adapters/commands/processPreviewResourcesCommand.d.ts +1 -1
- package/dist/adapters/commands/processPreviewResourcesCommand.js +14 -7
- package/dist/adapters/commands/renameFilesCommand.d.ts +10 -2
- package/dist/adapters/commands/renameFilesCommand.js +45 -17
- package/dist/adapters/commands/renameManifestCommand.d.ts +14 -0
- package/dist/adapters/commands/renameManifestCommand.js +32 -0
- package/dist/adapters/commands/writeResourcesCommand.d.ts +1 -1
- package/dist/adapters/commands/xsAppJsonEnhanceRoutesCommand.d.ts +1 -1
- package/dist/adapters/commands/xsAppJsonEnhanceRoutesCommand.js +4 -3
- package/dist/adapters/commands/xsAppJsonMergeCommand.d.ts +1 -1
- package/dist/adapters/commands/xsAppJsonMergeCommand.js +4 -3
- package/dist/adapters/previewAdapter.d.ts +2 -1
- package/dist/adapters/previewAdapter.js +3 -0
- package/dist/annotations/abapAnnotationManager.js +1 -1
- package/dist/annotations/dataSource/dataSourceManager.d.ts +2 -1
- package/dist/annotations/dataSource/dataSourceManager.js +16 -8
- package/dist/appVariant.d.ts +3 -3
- package/dist/appVariant.js +7 -7
- package/dist/baseApp.d.ts +3 -3
- package/dist/baseApp.js +4 -4
- package/dist/bundle.js +71 -34
- package/dist/cache/cacheHolder.d.ts +11 -2
- package/dist/cache/cacheHolder.js +23 -1
- package/dist/index.d.ts +10 -1
- package/dist/index.js +24 -4
- package/dist/landscapeConfiguration.d.ts +3 -3
- package/dist/landscapeConfiguration.js +38 -28
- package/dist/model/types.d.ts +5 -1
- package/dist/repositories/abapProvider.js +2 -2
- package/dist/repositories/abapRepository.d.ts +1 -1
- package/dist/repositories/cacheRepository.d.ts +10 -0
- package/dist/repositories/cacheRepository.js +29 -0
- package/dist/repositories/html5Repository.d.ts +1 -1
- package/dist/repositories/localRepository.d.ts +1 -1
- package/dist/repositories/repository.d.ts +1 -1
- package/dist/util/cfUtil.d.ts +6 -24
- package/dist/util/cfUtil.js +36 -93
- package/dist/util/commonUtil.d.ts +6 -1
- package/dist/util/commonUtil.js +16 -1
- package/dist/util/fsUtil.d.ts +2 -2
- package/dist/util/fsUtil.js +4 -4
- package/dist/util/manifestUtil.d.ts +6 -0
- package/dist/util/manifestUtil.js +15 -0
- package/dist/util/movingHandler/changeFileMoveHandler.d.ts +3 -3
- package/dist/util/movingHandler/changeFileMoveHandler.js +5 -4
- package/dist/util/renamingHandlers/jsonRenamingHandler.d.ts +6 -5
- package/dist/util/renamingHandlers/jsonRenamingHandler.js +15 -15
- package/dist/util/renamingUtil.d.ts +17 -0
- package/dist/util/renamingUtil.js +102 -81
- package/dist/util/resourceUtil.d.ts +15 -6
- package/dist/util/resourceUtil.js +50 -14
- package/dist/util/validator/abapConnectionValidator.d.ts +5 -0
- package/dist/util/validator/abapConnectionValidator.js +22 -0
- package/dist/util/validator/abapValidator.d.ts +2 -4
- package/dist/util/validator/abapValidator.js +4 -16
- package/dist/util/zipUtil.d.ts +1 -1
- package/dist/util/zipUtil.js +1 -1
- package/package.json +14 -8
- package/types/ui5.d.ts +2 -0
- package/dist/util/renamingHandlers/renamingHandler.d.ts +0 -4
- package/dist/util/renamingHandlers/renamingHandler.js +0 -2
|
@@ -1,39 +1,31 @@
|
|
|
1
|
-
import AbapAdapter from "./adapters/abapAdapter.js";
|
|
2
|
-
import CFAdapter from "./adapters/cfAdapter.js";
|
|
3
|
-
import PreviewAdapter from "./adapters/previewAdapter.js";
|
|
4
|
-
import AbapRepository from "./repositories/abapRepository.js";
|
|
5
|
-
import HTML5Repository from "./repositories/html5Repository.js";
|
|
6
|
-
import LocalRepository from "./repositories/localRepository.js";
|
|
7
|
-
import AbapAnnotationManager from "./annotations/abapAnnotationManager.js";
|
|
8
|
-
import CFAnnotationManager from "./annotations/cfAnnotationManager.js";
|
|
9
1
|
import CFValidator from "./util/validator/cfValidator.js";
|
|
10
|
-
import AbapValidator from "./util/validator/abapValidator.js";
|
|
11
2
|
import { isOneOf } from "./util/validator/validator.js";
|
|
12
3
|
import { LANDSCAPE_TYPES } from "./model/configuration.js";
|
|
13
4
|
import { getLogger } from "@ui5/logger";
|
|
5
|
+
import AbapValidator from "./util/validator/abapValidator.js";
|
|
14
6
|
import LocalAnnotationManager from "./annotations/localAnnotationManager.js";
|
|
15
7
|
const log = getLogger("@ui5/task-adaptation::LandscapeConfiguration");
|
|
16
|
-
export function initialize(configuration) {
|
|
17
|
-
const type = getTypeByConfiguration(configuration);
|
|
8
|
+
export async function initialize(configuration, options = {}) {
|
|
9
|
+
const type = await getTypeByConfiguration(configuration);
|
|
18
10
|
const enhancedConfig = { ...configuration, type };
|
|
19
|
-
const repository = getRepository(enhancedConfig);
|
|
20
|
-
const annotationManager = getAnnotationManager(enhancedConfig, repository);
|
|
11
|
+
const repository = await getRepository(enhancedConfig, options);
|
|
12
|
+
const annotationManager = await getAnnotationManager(enhancedConfig, repository);
|
|
21
13
|
return {
|
|
22
|
-
adapter: getAdapter(enhancedConfig, annotationManager),
|
|
14
|
+
adapter: await getAdapter(enhancedConfig, annotationManager),
|
|
23
15
|
repository,
|
|
24
16
|
annotationManager
|
|
25
17
|
};
|
|
26
18
|
}
|
|
27
|
-
function getTypeByConfiguration(configuration) {
|
|
28
|
-
const validators = [
|
|
29
|
-
new CFValidator(),
|
|
30
|
-
new AbapValidator(),
|
|
31
|
-
];
|
|
19
|
+
async function getTypeByConfiguration(configuration) {
|
|
32
20
|
if (isOneOf(LANDSCAPE_TYPES, configuration.type)) {
|
|
33
21
|
return configuration.type;
|
|
34
22
|
}
|
|
35
23
|
else {
|
|
36
24
|
log.warn("Deprecated behavior: type is not specified or invalid. Should be either 'cf' or 'abap'. Trying to detect the type based on provided configuration");
|
|
25
|
+
const validators = [
|
|
26
|
+
new CFValidator(),
|
|
27
|
+
new AbapValidator(),
|
|
28
|
+
];
|
|
37
29
|
for (const validator of validators) {
|
|
38
30
|
try {
|
|
39
31
|
validator.validateConfiguration(configuration);
|
|
@@ -46,41 +38,59 @@ function getTypeByConfiguration(configuration) {
|
|
|
46
38
|
throw new Error("'type' should be specified in ui5.yaml configuration: 'cf' or 'abap'");
|
|
47
39
|
}
|
|
48
40
|
}
|
|
49
|
-
function getAdapter(configuration, annotationManager) {
|
|
41
|
+
async function getAdapter(configuration, annotationManager) {
|
|
50
42
|
if (isPreview()) {
|
|
43
|
+
const { default: PreviewAdapter } = await import("./adapters/previewAdapter.js");
|
|
51
44
|
return new PreviewAdapter(configuration);
|
|
52
45
|
}
|
|
53
46
|
switch (configuration.type) {
|
|
54
|
-
case "abap":
|
|
47
|
+
case "abap": {
|
|
48
|
+
const { default: AbapAdapter } = await import("./adapters/abapAdapter.js");
|
|
55
49
|
return new AbapAdapter(annotationManager);
|
|
56
|
-
|
|
50
|
+
}
|
|
51
|
+
case "cf": {
|
|
52
|
+
const { default: CFAdapter } = await import("./adapters/cfAdapter.js");
|
|
57
53
|
return new CFAdapter(configuration);
|
|
54
|
+
}
|
|
58
55
|
default:
|
|
59
56
|
throw new Error(`No adapter found for the given configuration type '${configuration.type}'`);
|
|
60
57
|
}
|
|
61
58
|
}
|
|
62
|
-
function getRepository(configuration) {
|
|
59
|
+
async function getRepository(configuration, options) {
|
|
60
|
+
if (options.useCacheRepository) {
|
|
61
|
+
const { default: CacheRepository } = await import("./repositories/cacheRepository.js");
|
|
62
|
+
return new CacheRepository(configuration);
|
|
63
|
+
}
|
|
63
64
|
if (isLocal()) {
|
|
65
|
+
const { default: LocalRepository } = await import("./repositories/localRepository.js");
|
|
64
66
|
return new LocalRepository();
|
|
65
67
|
}
|
|
66
68
|
switch (configuration.type) {
|
|
67
|
-
case "abap":
|
|
69
|
+
case "abap": {
|
|
70
|
+
const { default: AbapRepository } = await import("./repositories/abapRepository.js");
|
|
68
71
|
return new AbapRepository(configuration);
|
|
69
|
-
|
|
72
|
+
}
|
|
73
|
+
case "cf": {
|
|
74
|
+
const { default: HTML5Repository } = await import("./repositories/html5Repository.js");
|
|
70
75
|
return new HTML5Repository(configuration);
|
|
76
|
+
}
|
|
71
77
|
default:
|
|
72
78
|
throw new Error(`No repository found for the given configuration type '${configuration.type}'`);
|
|
73
79
|
}
|
|
74
80
|
}
|
|
75
|
-
function getAnnotationManager(configuration, repository) {
|
|
81
|
+
async function getAnnotationManager(configuration, repository) {
|
|
76
82
|
if (isLocal()) {
|
|
77
83
|
return new LocalAnnotationManager();
|
|
78
84
|
}
|
|
79
85
|
switch (configuration.type) {
|
|
80
|
-
case "abap":
|
|
86
|
+
case "abap": {
|
|
87
|
+
const { default: AbapAnnotationManager } = await import("./annotations/abapAnnotationManager.js");
|
|
81
88
|
return new AbapAnnotationManager(configuration, repository);
|
|
82
|
-
|
|
89
|
+
}
|
|
90
|
+
case "cf": {
|
|
91
|
+
const { default: CFAnnotationManager } = await import("./annotations/cfAnnotationManager.js");
|
|
83
92
|
return new CFAnnotationManager();
|
|
93
|
+
}
|
|
84
94
|
default:
|
|
85
95
|
throw new Error(`No annotation manager found for the given configuration type '${configuration.type}'`);
|
|
86
96
|
}
|
package/dist/model/types.d.ts
CHANGED
|
@@ -22,6 +22,7 @@ export interface IGetServiceInstanceParams {
|
|
|
22
22
|
export interface IServiceInstance {
|
|
23
23
|
name: string;
|
|
24
24
|
guid: string;
|
|
25
|
+
type?: string;
|
|
25
26
|
}
|
|
26
27
|
export interface IResource {
|
|
27
28
|
name: string;
|
|
@@ -129,5 +130,8 @@ export type ServiceCredentials = {
|
|
|
129
130
|
} | string>;
|
|
130
131
|
"sap.cloud.service"?: string;
|
|
131
132
|
};
|
|
132
|
-
export type FetchFilesPromise = Map<string, Promise<ReadonlyMap<string,
|
|
133
|
+
export type FetchFilesPromise = Map<string, Promise<ReadonlyMap<string, Buffer>>>;
|
|
133
134
|
export { IConfiguration };
|
|
135
|
+
export interface IInitializeOptions {
|
|
136
|
+
useCacheRepository?: boolean;
|
|
137
|
+
}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { createAbapServiceProvider } from "@sap-ux/system-access";
|
|
2
2
|
import { getLogger } from "@ui5/logger";
|
|
3
|
-
import
|
|
3
|
+
import AbapConnectionValidator from "../util/validator/abapConnectionValidator.js";
|
|
4
4
|
const log = getLogger("@ui5/task-adaptation::AbapProvider");
|
|
5
5
|
log.debug = (message) => log.verbose(message);
|
|
6
6
|
export default class AbapProvider {
|
|
7
7
|
provider = null;
|
|
8
|
-
abapValidator = new
|
|
8
|
+
abapValidator = new AbapConnectionValidator();
|
|
9
9
|
async get({ target, destination }) {
|
|
10
10
|
if (!this.provider) {
|
|
11
11
|
const abapTarget = this.abapValidator.validateAndGetAbapTarget(target, destination);
|
|
@@ -11,6 +11,6 @@ export default class AbapRepository implements IRepository {
|
|
|
11
11
|
getAnnotationMetadata(uri: string): Promise<IMetadata>;
|
|
12
12
|
downloadAnnotationFile(uri: string): Promise<Map<string, any>>;
|
|
13
13
|
getMetadata(id: string): Promise<IMetadata>;
|
|
14
|
-
fetch(resource: IAbapResource): Promise<Map<string,
|
|
14
|
+
fetch(resource: IAbapResource): Promise<Map<string, Buffer>>;
|
|
15
15
|
}
|
|
16
16
|
export {};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import ICachedResource from "../cache/cachedResource.js";
|
|
2
|
+
import { IConfiguration } from "../model/types.js";
|
|
3
|
+
import IRepository from "./repository.js";
|
|
4
|
+
export default class CacheRepository implements IRepository {
|
|
5
|
+
private configuration;
|
|
6
|
+
constructor(configuration: IConfiguration);
|
|
7
|
+
getAppVariantIdHierarchy(_appId: string): Promise<ICachedResource[]>;
|
|
8
|
+
fetch(resource: ICachedResource): Promise<Map<string, Buffer>>;
|
|
9
|
+
downloadAnnotationFile(uri: string): Promise<Map<string, string>>;
|
|
10
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import CacheHolder from "../cache/cacheHolder.js";
|
|
2
|
+
export default class CacheRepository {
|
|
3
|
+
configuration;
|
|
4
|
+
constructor(configuration) {
|
|
5
|
+
this.configuration = configuration;
|
|
6
|
+
}
|
|
7
|
+
async getAppVariantIdHierarchy(_appId) {
|
|
8
|
+
const { appName } = this.configuration;
|
|
9
|
+
if (!appName) {
|
|
10
|
+
throw new Error("previewManifest requires 'appName' in the ui5.yaml configuration");
|
|
11
|
+
}
|
|
12
|
+
return [{
|
|
13
|
+
appName,
|
|
14
|
+
cacheBusterToken: Promise.resolve("")
|
|
15
|
+
}];
|
|
16
|
+
}
|
|
17
|
+
async fetch(resource) {
|
|
18
|
+
const appName = resource.appName;
|
|
19
|
+
const cachedFiles = await CacheHolder.readLatest(appName);
|
|
20
|
+
if (cachedFiles.size === 0) {
|
|
21
|
+
throw new Error(`No cached base app found for '${appName}'. Please check the appName or run a full build first to populate the cache.`);
|
|
22
|
+
}
|
|
23
|
+
return cachedFiles;
|
|
24
|
+
}
|
|
25
|
+
downloadAnnotationFile(uri) {
|
|
26
|
+
throw new Error(`Download annotation file for uri: ${uri} is not available for CacheRepository.`);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=cacheRepository.js.map
|
|
@@ -10,7 +10,7 @@ export default class HTML5Repository implements IRepository {
|
|
|
10
10
|
private validator;
|
|
11
11
|
constructor(configuration: IConfiguration);
|
|
12
12
|
getAppVariantIdHierarchy(_appId: string): Promise<IHtml5Resource[]>;
|
|
13
|
-
fetch(resource: IHtml5Resource): Promise<Map<string,
|
|
13
|
+
fetch(resource: IHtml5Resource): Promise<Map<string, Buffer>>;
|
|
14
14
|
getMetadata(): Promise<any>;
|
|
15
15
|
private getHtml5RepoInfo;
|
|
16
16
|
private getHTML5Credentials;
|
|
@@ -6,7 +6,7 @@ export interface ILocalResource extends ICachedResource {
|
|
|
6
6
|
export default class LocalRepository implements IRepository {
|
|
7
7
|
downloadAnnotationFile(_uri: string): Promise<Map<string, string>>;
|
|
8
8
|
getAppVariantIdHierarchy(appId: string): Promise<ILocalResource[]>;
|
|
9
|
-
fetch(resource: ILocalResource): Promise<Map<string,
|
|
9
|
+
fetch(resource: ILocalResource): Promise<Map<string, Buffer>>;
|
|
10
10
|
private buildManifestIndex;
|
|
11
11
|
private getLocalFilesDir;
|
|
12
12
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import ICachedResource from "../cache/cachedResource.js";
|
|
2
2
|
export default interface IRepository {
|
|
3
3
|
getAppVariantIdHierarchy(appId: string): Promise<ICachedResource[]>;
|
|
4
|
-
fetch(resource: ICachedResource): Promise<Map<string,
|
|
4
|
+
fetch(resource: ICachedResource): Promise<Map<string, Buffer>>;
|
|
5
5
|
downloadAnnotationFile(uri: string): Promise<Map<string, string>>;
|
|
6
6
|
}
|
package/dist/util/cfUtil.d.ts
CHANGED
|
@@ -10,10 +10,9 @@ export default class CFUtil {
|
|
|
10
10
|
*/
|
|
11
11
|
static getServiceInstanceKeys(getServiceInstanceParams: IGetServiceInstanceParams, createServiceInstanceParams?: ICreateServiceInstanceParams): Promise<IServiceKeys>;
|
|
12
12
|
static createService(params: ICreateServiceInstanceParams): Promise<void>;
|
|
13
|
-
private static
|
|
14
|
-
private static
|
|
13
|
+
private static getOrCreateCredentials;
|
|
14
|
+
private static fetchCredentials;
|
|
15
15
|
private static createServiceKey;
|
|
16
|
-
private static deleteServiceKeyUnsafe;
|
|
17
16
|
private static getServiceInstance;
|
|
18
17
|
static processCfErrors(errors?: ICfError[]): void;
|
|
19
18
|
static requestCfApi(url: string): Promise<IResource[]>;
|
|
@@ -22,14 +21,15 @@ export default class CFUtil {
|
|
|
22
21
|
private static errorsToString;
|
|
23
22
|
private static parseJson;
|
|
24
23
|
/**
|
|
25
|
-
*
|
|
24
|
+
* Return the most recently created service credential binding (key) for the given service instance,
|
|
25
|
+
* or undefined if no keys exist.
|
|
26
26
|
* @private
|
|
27
27
|
* @static
|
|
28
28
|
* @param {string} serviceInstanceGuid the service instance guid
|
|
29
|
-
* @return {Promise<
|
|
29
|
+
* @return {Promise<any | undefined>} the newest binding object ({ name, guid, created_at, … }) or undefined
|
|
30
30
|
* @memberof CFUtil
|
|
31
31
|
*/
|
|
32
|
-
private static
|
|
32
|
+
private static getNewestServiceKey;
|
|
33
33
|
/**
|
|
34
34
|
* Get service keys for a service instance by name. If the existing service key
|
|
35
35
|
* has endpoints as strings instead of objects, a new service key will be created.
|
|
@@ -49,24 +49,6 @@ export default class CFUtil {
|
|
|
49
49
|
* @memberof CFUtil
|
|
50
50
|
*/
|
|
51
51
|
private static hasValidEndpoints;
|
|
52
|
-
/**
|
|
53
|
-
* Get all service key names for a service instance
|
|
54
|
-
* @private
|
|
55
|
-
* @static
|
|
56
|
-
* @param {string} serviceInstanceGuid the service instance guid
|
|
57
|
-
* @return {Promise<string[]>} promise with array of service key names
|
|
58
|
-
* @memberof CFUtil
|
|
59
|
-
*/
|
|
60
|
-
private static getAllServiceKeyNames;
|
|
61
|
-
/**
|
|
62
|
-
* Generate a unique service key name in format serviceInstanceName-key-N
|
|
63
|
-
* @static
|
|
64
|
-
* @param {string} serviceInstanceName the service instance name
|
|
65
|
-
* @param {string} serviceInstanceGuid the service instance guid
|
|
66
|
-
* @return {Promise<string>} promise with unique service key name
|
|
67
|
-
* @memberof CFUtil
|
|
68
|
-
*/
|
|
69
|
-
static generateUniqueServiceKeyName(serviceInstanceName: string, serviceInstanceGuid: string): Promise<string>;
|
|
70
52
|
/**
|
|
71
53
|
* Get space guid from configuration or local CF fodler
|
|
72
54
|
* @static
|
package/dist/util/cfUtil.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import { cfCreateService
|
|
1
|
+
import { cfCreateService } from "@sap/cf-tools/out/src/cf-local.js";
|
|
2
2
|
import { getSpaceGuidThrowIfUndefined } from "@sap/cf-tools/out/src/utils.js";
|
|
3
3
|
import { Cli } from "@sap/cf-tools/out/src/cli.js";
|
|
4
|
-
import { eFilters } from "@sap/cf-tools/out/src/types.js";
|
|
5
4
|
import { getLogger } from "@ui5/logger";
|
|
6
5
|
import AuthenticationError from "../model/authenticationError.js";
|
|
7
6
|
const log = getLogger("@ui5/task-adaptation::CFUtil");
|
|
@@ -25,12 +24,12 @@ export default class CFUtil {
|
|
|
25
24
|
}
|
|
26
25
|
// we can use any instance in the list to connect to HTML5 Repo
|
|
27
26
|
log.verbose(`Use '${serviceInstances[0].name}' HTML5 Repo Runtime service instance`);
|
|
28
|
-
const
|
|
29
|
-
if (!
|
|
27
|
+
const credentials = await this.getOrCreateCredentials(serviceInstances[0]);
|
|
28
|
+
if (!credentials) {
|
|
30
29
|
throw new Error(`Cannot get service keys for '${getServiceInstanceParams.names?.join(", ")}' service in current space: ${getServiceInstanceParams.spaceGuids?.join(", ")}`);
|
|
31
30
|
}
|
|
32
31
|
return {
|
|
33
|
-
credentials
|
|
32
|
+
credentials,
|
|
34
33
|
serviceInstance: serviceInstances[0]
|
|
35
34
|
};
|
|
36
35
|
}
|
|
@@ -52,27 +51,28 @@ export default class CFUtil {
|
|
|
52
51
|
throw new Error(`Cannot create a service instance '${params.serviceInstanceName}' in space '${params.spaceGuid}': ${error.message}`);
|
|
53
52
|
}
|
|
54
53
|
}
|
|
55
|
-
static async
|
|
56
|
-
|
|
57
|
-
|
|
54
|
+
static async getOrCreateCredentials(serviceInstance) {
|
|
55
|
+
if (serviceInstance.type === "user-provided") {
|
|
56
|
+
log.verbose(`Service instance '${serviceInstance.name}' is user-provided, fetching credentials directly`);
|
|
57
|
+
return this.fetchCredentials(`/v3/service_instances/${serviceInstance.guid}/credentials`);
|
|
58
|
+
}
|
|
59
|
+
let key = await this.getNewestServiceKey(serviceInstance.guid);
|
|
60
|
+
if (key == null) {
|
|
58
61
|
const serviceKeyName = serviceInstance.name + "_key";
|
|
59
62
|
log.info(`Creating service key '${serviceKeyName}' for service instance '${serviceInstance.name}'`);
|
|
60
63
|
await this.createServiceKey(serviceInstance.name, serviceKeyName);
|
|
64
|
+
key = await this.getNewestServiceKey(serviceInstance.guid);
|
|
65
|
+
if (key == null) {
|
|
66
|
+
throw new Error(`Service key was created for '${serviceInstance.name}' but could not be retrieved`);
|
|
67
|
+
}
|
|
61
68
|
}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
}
|
|
65
|
-
return this.getServiceKeys(serviceInstance.guid);
|
|
69
|
+
log.verbose(`Using service key '${key.name}' for service instance '${serviceInstance.name}'`);
|
|
70
|
+
return this.fetchCredentials(`/v3/service_credential_bindings/${key.guid}/details`);
|
|
66
71
|
}
|
|
67
|
-
static
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
key: eFilters.service_instance_guids
|
|
72
|
-
}]
|
|
73
|
-
}).catch((error) => {
|
|
74
|
-
throw new Error("Failed to get service credentials: " + error.message);
|
|
75
|
-
});
|
|
72
|
+
static async fetchCredentials(url) {
|
|
73
|
+
const parsed = this.parseJson(await this.cfExecute(["curl", url]));
|
|
74
|
+
this.processCfErrors(parsed?.errors);
|
|
75
|
+
return parsed.credentials;
|
|
76
76
|
}
|
|
77
77
|
static async createServiceKey(serviceInstanceName, serviceKeyName) {
|
|
78
78
|
try {
|
|
@@ -82,12 +82,6 @@ export default class CFUtil {
|
|
|
82
82
|
throw new Error(`Couldn't create a service key for instance: ${serviceInstanceName}: ${error}`);
|
|
83
83
|
}
|
|
84
84
|
}
|
|
85
|
-
static deleteServiceKeyUnsafe(serviceInstanceName, serviceKeyName) {
|
|
86
|
-
// Fire and forget - async delete without waiting for result or handling errors
|
|
87
|
-
this.cfExecute(["delete-service-key", serviceInstanceName, serviceKeyName, "-f"]).catch(() => {
|
|
88
|
-
// Ignore any errors - this is intentionally unsafe
|
|
89
|
-
});
|
|
90
|
-
}
|
|
91
85
|
static async getServiceInstance(params) {
|
|
92
86
|
const PARAM_MAP = {
|
|
93
87
|
spaceGuids: "space_guids",
|
|
@@ -101,7 +95,8 @@ export default class CFUtil {
|
|
|
101
95
|
const resources = await this.requestCfApi(uri);
|
|
102
96
|
return resources.map((service) => ({
|
|
103
97
|
name: service.name,
|
|
104
|
-
guid: service.guid
|
|
98
|
+
guid: service.guid,
|
|
99
|
+
type: service.type
|
|
105
100
|
}));
|
|
106
101
|
}
|
|
107
102
|
static processCfErrors(errors) {
|
|
@@ -174,18 +169,21 @@ export default class CFUtil {
|
|
|
174
169
|
}
|
|
175
170
|
}
|
|
176
171
|
/**
|
|
177
|
-
*
|
|
172
|
+
* Return the most recently created service credential binding (key) for the given service instance,
|
|
173
|
+
* or undefined if no keys exist.
|
|
178
174
|
* @private
|
|
179
175
|
* @static
|
|
180
176
|
* @param {string} serviceInstanceGuid the service instance guid
|
|
181
|
-
* @return {Promise<
|
|
177
|
+
* @return {Promise<any | undefined>} the newest binding object ({ name, guid, created_at, … }) or undefined
|
|
182
178
|
* @memberof CFUtil
|
|
183
179
|
*/
|
|
184
|
-
static async
|
|
180
|
+
static async getNewestServiceKey(serviceInstanceGuid) {
|
|
185
181
|
try {
|
|
186
|
-
const
|
|
187
|
-
|
|
188
|
-
|
|
182
|
+
const keyList = await this.requestCfApi(`/v3/service_credential_bindings?type=key&service_instance_guids=${serviceInstanceGuid}`);
|
|
183
|
+
if (!keyList?.length) {
|
|
184
|
+
return undefined;
|
|
185
|
+
}
|
|
186
|
+
return keyList.toSorted((a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime())[0];
|
|
189
187
|
}
|
|
190
188
|
catch (error) {
|
|
191
189
|
throw new Error("Failed to get service credentials: " + error.message);
|
|
@@ -212,30 +210,11 @@ export default class CFUtil {
|
|
|
212
210
|
}
|
|
213
211
|
const serviceInstance = serviceInstances[0];
|
|
214
212
|
log.verbose(`Found service instance '${serviceInstance.name}' with guid: ${serviceInstance.guid}`);
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
// object with url and destination instead of a single url string
|
|
219
|
-
const validKey = await this.getServiceKeyWithValidEndpoints(serviceInstance.guid);
|
|
220
|
-
if (validKey) {
|
|
221
|
-
log.verbose(`Using existing service key with valid endpoints structure`);
|
|
222
|
-
return validKey.credentials;
|
|
223
|
-
}
|
|
224
|
-
const uniqueServiceKeyName = await uniqueServiceKeyNamePromise;
|
|
225
|
-
log.verbose(`No valid service key found with proper endpoints structure. Creating new service key '${uniqueServiceKeyName}' for '${serviceInstance.name}'`);
|
|
226
|
-
await this.createServiceKey(serviceInstance.name, uniqueServiceKeyName);
|
|
227
|
-
// Get the newly created service key and validate its endpoints
|
|
228
|
-
const newValidKey = await this.getServiceKeyWithValidEndpoints(serviceInstance.guid);
|
|
229
|
-
if (newValidKey) {
|
|
230
|
-
log.verbose(`Using newly created service key with valid endpoints structure`);
|
|
231
|
-
return newValidKey.credentials;
|
|
213
|
+
const credentials = await this.getOrCreateCredentials(serviceInstance);
|
|
214
|
+
if (!credentials?.endpoints || !this.hasValidEndpoints(credentials.endpoints)) {
|
|
215
|
+
log.info(`Service key for '${serviceInstance.name}' does not have endpoints with service urls for xs-app.json update`);
|
|
232
216
|
}
|
|
233
|
-
|
|
234
|
-
// endpoints. We don't throw an error here even if no valid endpoints
|
|
235
|
-
// found. We assume that there might be no coincidence between
|
|
236
|
-
// credential endpoints and xs-app.json destinations.
|
|
237
|
-
this.deleteServiceKeyUnsafe(serviceInstance.name, uniqueServiceKeyName);
|
|
238
|
-
log.verbose(`Created service key '${uniqueServiceKeyName}' does not have valid endpoints structure. Triggered deletion of invalid service key '${uniqueServiceKeyName}'`);
|
|
217
|
+
return credentials;
|
|
239
218
|
}
|
|
240
219
|
/**
|
|
241
220
|
* Check if endpoints object has at least one property that is an object
|
|
@@ -252,42 +231,6 @@ export default class CFUtil {
|
|
|
252
231
|
// Check if at least one property of endpoints is an object
|
|
253
232
|
return Object.values(endpoints).some(value => value && typeof value === 'object' && !Array.isArray(value));
|
|
254
233
|
}
|
|
255
|
-
/**
|
|
256
|
-
* Get all service key names for a service instance
|
|
257
|
-
* @private
|
|
258
|
-
* @static
|
|
259
|
-
* @param {string} serviceInstanceGuid the service instance guid
|
|
260
|
-
* @return {Promise<string[]>} promise with array of service key names
|
|
261
|
-
* @memberof CFUtil
|
|
262
|
-
*/
|
|
263
|
-
static async getAllServiceKeyNames(serviceInstanceGuid) {
|
|
264
|
-
try {
|
|
265
|
-
const serviceKeys = await this.requestCfApi(`/v3/service_credential_bindings?type=key&service_instance_guids=${serviceInstanceGuid}`);
|
|
266
|
-
return serviceKeys.map((key) => key.name);
|
|
267
|
-
}
|
|
268
|
-
catch (error) {
|
|
269
|
-
throw new Error(`Failed to get service key names: ${error.message}`);
|
|
270
|
-
}
|
|
271
|
-
}
|
|
272
|
-
/**
|
|
273
|
-
* Generate a unique service key name in format serviceInstanceName-key-N
|
|
274
|
-
* @static
|
|
275
|
-
* @param {string} serviceInstanceName the service instance name
|
|
276
|
-
* @param {string} serviceInstanceGuid the service instance guid
|
|
277
|
-
* @return {Promise<string>} promise with unique service key name
|
|
278
|
-
* @memberof CFUtil
|
|
279
|
-
*/
|
|
280
|
-
static async generateUniqueServiceKeyName(serviceInstanceName, serviceInstanceGuid) {
|
|
281
|
-
const existingKeyNames = await this.getAllServiceKeyNames(serviceInstanceGuid);
|
|
282
|
-
let counter = 0;
|
|
283
|
-
let keyName;
|
|
284
|
-
do {
|
|
285
|
-
keyName = `${serviceInstanceName}-key-${counter}`;
|
|
286
|
-
counter++;
|
|
287
|
-
} while (existingKeyNames.includes(keyName));
|
|
288
|
-
log.verbose(`Generated unique service key name: ${keyName}`);
|
|
289
|
-
return keyName;
|
|
290
|
-
}
|
|
291
234
|
/**
|
|
292
235
|
* Get space guid from configuration or local CF fodler
|
|
293
236
|
* @static
|
|
@@ -2,6 +2,11 @@ import { IConfiguration } from "../model/types.js";
|
|
|
2
2
|
import Language from "../model/language.js";
|
|
3
3
|
import AppVariant from "../appVariant.js";
|
|
4
4
|
export declare function dotToUnderscore(value: string): string;
|
|
5
|
+
export declare function bufferToString(buffer: Buffer): string;
|
|
6
|
+
export declare function bufferToJson(buffer: Buffer): any;
|
|
7
|
+
export declare function bufferToNormalizedString(buffer: Buffer): string;
|
|
8
|
+
export declare function stringToBuffer(value: string): Buffer;
|
|
9
|
+
export declare function jsonToBuffer(json: any): Buffer;
|
|
5
10
|
export declare function validateConfiguration<T extends object>(options: T, properties: Array<keyof T>): void;
|
|
6
11
|
export declare function validateObject<T extends object>(options: T, properties: Array<keyof T>, message: string): void;
|
|
7
12
|
export declare function escapeRegex(update: string): string;
|
|
@@ -12,7 +17,7 @@ export declare function traverse(json: any, paths: string[], callback: (json: an
|
|
|
12
17
|
export declare function logBuilderVersion(): void;
|
|
13
18
|
export declare function logBetaUsage(): void;
|
|
14
19
|
export declare function getUniqueName(existingNames: string[], template: string): string;
|
|
15
|
-
export declare function isManifestChange(filename: string, content:
|
|
20
|
+
export declare function isManifestChange(filename: string, content: Buffer): boolean;
|
|
16
21
|
/**
|
|
17
22
|
* 4p. Reference map contains searchTerm as key and replacement as value. Base
|
|
18
23
|
* id and app variant ids are renamed to adaptation project id.
|
package/dist/util/commonUtil.js
CHANGED
|
@@ -9,6 +9,21 @@ const MANIFEST_CHANGE = "appdescr_";
|
|
|
9
9
|
export function dotToUnderscore(value) {
|
|
10
10
|
return value.replace(/\./g, "_");
|
|
11
11
|
}
|
|
12
|
+
export function bufferToString(buffer) {
|
|
13
|
+
return buffer.toString("utf8");
|
|
14
|
+
}
|
|
15
|
+
export function bufferToJson(buffer) {
|
|
16
|
+
return JSON.parse(bufferToString(buffer));
|
|
17
|
+
}
|
|
18
|
+
export function bufferToNormalizedString(buffer) {
|
|
19
|
+
return bufferToString(buffer).replaceAll("\r\n", "\n");
|
|
20
|
+
}
|
|
21
|
+
export function stringToBuffer(value) {
|
|
22
|
+
return Buffer.from(value, "utf8");
|
|
23
|
+
}
|
|
24
|
+
export function jsonToBuffer(json) {
|
|
25
|
+
return stringToBuffer(JSON.stringify(json));
|
|
26
|
+
}
|
|
12
27
|
export function validateConfiguration(options, properties) {
|
|
13
28
|
validateObject(options, properties, "should be specified in ui5.yaml configuration");
|
|
14
29
|
}
|
|
@@ -93,7 +108,7 @@ export function getUniqueName(existingNames, template) {
|
|
|
93
108
|
}
|
|
94
109
|
export function isManifestChange(filename, content) {
|
|
95
110
|
if (filename.endsWith(CHANGES_EXT)) {
|
|
96
|
-
const change =
|
|
111
|
+
const change = bufferToJson(content);
|
|
97
112
|
return change.changeType?.startsWith(MANIFEST_CHANGE);
|
|
98
113
|
}
|
|
99
114
|
return false;
|
package/dist/util/fsUtil.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
export default class FsUtil {
|
|
2
|
-
static readInProject(filepath: string
|
|
2
|
+
static readInProject(filepath: string): Promise<Buffer>;
|
|
3
3
|
/**
|
|
4
4
|
* Check whether a file or directory exists (non-throwing).
|
|
5
5
|
* @param filePath Absolute or relative path
|
|
6
6
|
* @returns true if the path exists, false if not
|
|
7
7
|
*/
|
|
8
8
|
private static fileExists;
|
|
9
|
-
static readFilesRecursively(rootDirectory: string): Promise<Map<string,
|
|
9
|
+
static readFilesRecursively(rootDirectory: string): Promise<Map<string, Buffer>>;
|
|
10
10
|
}
|
package/dist/util/fsUtil.js
CHANGED
|
@@ -5,11 +5,11 @@ export default class FsUtil {
|
|
|
5
5
|
* Read the file by filepath from the project root (folder where 'webapp',
|
|
6
6
|
* 'package.json', 'ui5.yaml' located).
|
|
7
7
|
* @param filepath The relative file path from the project root (e.g. 'ui5AppInfo.json').
|
|
8
|
-
* @returns A promise that resolves to the file content as a
|
|
8
|
+
* @returns A promise that resolves to the file content as a Buffer.
|
|
9
9
|
*/
|
|
10
|
-
static async readInProject(filepath
|
|
10
|
+
static async readInProject(filepath) {
|
|
11
11
|
try {
|
|
12
|
-
return await fs.readFile(path.join(process.cwd(), filepath)
|
|
12
|
+
return await fs.readFile(path.join(process.cwd(), filepath));
|
|
13
13
|
}
|
|
14
14
|
catch (error) {
|
|
15
15
|
const isProjectRoot = await FsUtil.fileExists(path.join(process.cwd(), "ui5.yaml"));
|
|
@@ -44,7 +44,7 @@ export default class FsUtil {
|
|
|
44
44
|
const parentPath = entry.parentPath ?? entry.path; // node v20.11.0 fallback
|
|
45
45
|
const entryPath = path.join(parentPath, entry.name);
|
|
46
46
|
const relativeFilePath = path.relative(rootDirectory, entryPath).replaceAll("\\", "/");
|
|
47
|
-
const content = await fs.readFile(entryPath
|
|
47
|
+
const content = await fs.readFile(entryPath);
|
|
48
48
|
return [relativeFilePath, content];
|
|
49
49
|
});
|
|
50
50
|
return new Map(await Promise.all(fileReadTasks));
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Returns the SAPUI5 dependency ids (libs and components) declared under
|
|
3
|
+
* "sap.ui5"/dependencies of a parsed manifest. These point at other apps and
|
|
4
|
+
* must not be renamed, so callers add them to the renamer ignore list.
|
|
5
|
+
*/
|
|
6
|
+
export declare function getSAPUI5DependencyIds(manifest: any): string[];
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Returns the SAPUI5 dependency ids (libs and components) declared under
|
|
3
|
+
* "sap.ui5"/dependencies of a parsed manifest. These point at other apps and
|
|
4
|
+
* must not be renamed, so callers add them to the renamer ignore list.
|
|
5
|
+
*/
|
|
6
|
+
export function getSAPUI5DependencyIds(manifest) {
|
|
7
|
+
const dependencies = manifest?.["sap.ui5"]?.dependencies;
|
|
8
|
+
if (!dependencies) {
|
|
9
|
+
return [];
|
|
10
|
+
}
|
|
11
|
+
const libs = dependencies.libs ? Object.keys(dependencies.libs) : [];
|
|
12
|
+
const components = dependencies.components ? Object.keys(dependencies.components) : [];
|
|
13
|
+
return [...libs, ...components];
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=manifestUtil.js.map
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
export declare const moveFiles: (inputFiles: ReadonlyMap<string,
|
|
2
|
-
files: Map<string,
|
|
1
|
+
export declare const moveFiles: (inputFiles: ReadonlyMap<string, Buffer>, prefix: string, id: string) => {
|
|
2
|
+
files: Map<string, Buffer<ArrayBufferLike>>;
|
|
3
3
|
renamingPaths: Map<string, string>;
|
|
4
4
|
};
|
|
5
|
-
export declare const moveFile: (filename: string, content:
|
|
5
|
+
export declare const moveFile: (filename: string, content: Buffer, prefix: string, id: string) => {
|
|
6
6
|
newFilename: string;
|
|
7
7
|
renamingPath: Map<string, string>;
|
|
8
8
|
};
|