@ui5/task-adaptation 1.4.2 → 1.5.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/CHANGELOG.md +16 -1
- package/README.md +16 -12
- package/REUSE.toml +10 -0
- package/dist/annotationManager.d.ts +1 -1
- package/dist/annotationManager.js +5 -8
- package/dist/annotations/dataSource/dataSource.js +0 -1
- package/dist/annotations/serviceRequestor.js +3 -15
- package/dist/appVariantManager.d.ts +16 -11
- package/dist/appVariantManager.js +56 -83
- package/dist/baseAppManager.d.ts +16 -16
- package/dist/baseAppManager.js +58 -81
- package/dist/bundle.d.ts +2 -3
- package/dist/bundle.js +3834 -3490
- package/dist/cache/cacheHolder.d.ts +18 -0
- package/dist/cache/cacheHolder.js +80 -0
- package/dist/i18nManager.js +11 -9
- package/dist/index.js +34 -9
- package/dist/model/appVariantIdHierarchyItem.d.ts +5 -0
- package/dist/model/appVariantIdHierarchyItem.js +2 -0
- package/dist/model/configuration.d.ts +2 -2
- package/dist/model/language.d.ts +3 -3
- package/dist/model/language.js +11 -4
- package/dist/model/types.d.ts +3 -1
- package/dist/processors/abapProcessor.d.ts +5 -5
- package/dist/processors/abapProcessor.js +19 -7
- package/dist/processors/cfProcessor.d.ts +4 -4
- package/dist/processors/cfProcessor.js +29 -13
- package/dist/processors/processor.d.ts +4 -2
- package/dist/processors/processor.js +3 -5
- package/dist/repositories/abapRepoManager.d.ts +3 -1
- package/dist/repositories/abapRepoManager.js +24 -5
- package/dist/repositories/html5RepoManager.js +3 -2
- package/dist/util/cfUtil.d.ts +1 -0
- package/dist/util/cfUtil.js +27 -23
- package/dist/util/commonUtil.d.ts +5 -3
- package/dist/util/commonUtil.js +104 -31
- package/dist/util/filesUtil.d.ts +17 -0
- package/dist/util/filesUtil.js +49 -0
- package/dist/util/i18nMerger.d.ts +15 -20
- package/dist/util/i18nMerger.js +46 -64
- package/dist/util/renamingHandlers/manifestHandler.d.ts +6 -0
- package/dist/util/renamingHandlers/manifestHandler.js +20 -0
- package/dist/util/renamingHandlers/renamingHandler.d.ts +4 -0
- package/dist/util/renamingHandlers/renamingHandler.js +2 -0
- package/dist/util/requestUtil.d.ts +2 -1
- package/dist/util/resourceUtil.d.ts +3 -1
- package/dist/util/resourceUtil.js +15 -2
- package/eslint.config.js +20 -4
- package/package.json +28 -22
- package/scripts/rollup/bundle.d.ts +2 -3
- package/scripts/rollup/bundleDefinition.js +2 -2
- package/scripts/rollup/overrides/sap/ui/fl/Utils.js +13 -0
- package/scripts/rollup/overrides/sap/ui/fl/apply/_internal/changes/FlexCustomData.js +13 -0
- package/scripts/rollup/overrides/sap/ui/fl/apply/_internal/flexObjects/AnnotationChange.js +11 -0
- package/scripts/rollup/overrides/sap/ui/fl/apply/_internal/flexObjects/AppDescriptorChange.js +68 -0
- package/scripts/rollup/overrides/sap/ui/fl/apply/_internal/flexObjects/VariantChange.js +11 -0
- package/scripts/rollup/overrides/sap/ui/fl/apply/_internal/flexObjects/VariantManagementChange.js +11 -0
- package/scripts/rollup/overrides/sap/ui/fl/apply/_internal/flexState/controlVariants/VariantManagementState.js +13 -0
- package/scripts/rollup/overrides/sap/ui/fl/initial/_internal/changeHandlers/ChangeHandlerRegistration.js +13 -0
- package/scripts/rollup/overrides/sap/ui/fl/initial/_internal/changeHandlers/ChangeHandlerStorage.js +14 -0
- package/scripts/rollup/project/ui5.yaml +1 -1
- package/scripts/test-integration-prep.sh +4 -0
- package/types/ui5.d.ts +10 -0
- package/dist/cache/annotationsCacheManager.d.ts +0 -8
- package/dist/cache/annotationsCacheManager.js +0 -16
- package/dist/cache/baseAppFilesCacheManager.d.ts +0 -6
- package/dist/cache/baseAppFilesCacheManager.js +0 -12
- package/dist/cache/cacheManager.d.ts +0 -16
- package/dist/cache/cacheManager.js +0 -65
- package/scripts/rollup/overrides/sap/ui/fl/Change.js +0 -74
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export default class CacheHolder {
|
|
2
|
+
private static TEMP_TASK_DIR;
|
|
3
|
+
private static getTempDir;
|
|
4
|
+
static read(repoName: string, token: string): Map<string, string> | undefined;
|
|
5
|
+
static write(repoName: string, token: string, files: Map<string, string>): Promise<void>;
|
|
6
|
+
private static isValid;
|
|
7
|
+
/**
|
|
8
|
+
* Clears cached files by repo name and token
|
|
9
|
+
*/
|
|
10
|
+
static delete(...paths: string[]): void;
|
|
11
|
+
/**
|
|
12
|
+
* Clears all cached files
|
|
13
|
+
*/
|
|
14
|
+
static clear(): void;
|
|
15
|
+
private static deleteDir;
|
|
16
|
+
static clearOutdatedExcept(repoName?: string, maxAgeMs?: number): Promise<void>;
|
|
17
|
+
}
|
|
18
|
+
export declare function cached(): (_target: any, _propertyKey: string, descriptor: PropertyDescriptor) => void;
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import * as fs from "fs";
|
|
2
|
+
import * as fsPromises from "fs/promises";
|
|
3
|
+
import * as path from "path";
|
|
4
|
+
import ResourceUtil from "../util/resourceUtil.js";
|
|
5
|
+
import encodeFilename from "filenamify";
|
|
6
|
+
import { getLogger } from "@ui5/logger";
|
|
7
|
+
import tempDir from "temp-dir";
|
|
8
|
+
const log = getLogger("@ui5/task-adaptation::CacheHolder");
|
|
9
|
+
export default class CacheHolder {
|
|
10
|
+
static TEMP_TASK_DIR = "ui5-task-adaptation";
|
|
11
|
+
static getTempDir(...paths) {
|
|
12
|
+
return path.join(tempDir, this.TEMP_TASK_DIR, ...paths.map(part => encodeFilename(part, { replacement: "_" })));
|
|
13
|
+
}
|
|
14
|
+
static read(repoName, token) {
|
|
15
|
+
const directory = this.getTempDir(repoName, token);
|
|
16
|
+
if (this.isValid(repoName, "repoName") && this.isValid(token, "token") && fs.existsSync(directory)) {
|
|
17
|
+
return ResourceUtil.read(directory);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
static async write(repoName, token, files) {
|
|
21
|
+
this.delete(repoName);
|
|
22
|
+
if (this.isValid(repoName, "repoName") && this.isValid(token, "token")) {
|
|
23
|
+
await ResourceUtil.write(this.getTempDir(repoName, token), files);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
static isValid(value, name) {
|
|
27
|
+
if (value == null || value === "") {
|
|
28
|
+
log.warn(`No '${name}' provided, skipping cache write`);
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
return true;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Clears cached files by repo name and token
|
|
35
|
+
*/
|
|
36
|
+
static delete(...paths) {
|
|
37
|
+
this.deleteDir(this.getTempDir(...paths));
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Clears all cached files
|
|
41
|
+
*/
|
|
42
|
+
static clear() {
|
|
43
|
+
this.deleteDir(path.join(tempDir, this.TEMP_TASK_DIR));
|
|
44
|
+
}
|
|
45
|
+
static deleteDir(directory) {
|
|
46
|
+
if (fs.existsSync(directory)) {
|
|
47
|
+
fs.rmSync(directory, { recursive: true, force: true });
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
static async clearOutdatedExcept(repoName, maxAgeMs = 1000 * 60 * 60 * 24 * 30) {
|
|
51
|
+
const MAX_AGE = Date.now() - maxAgeMs; // 30 days by default
|
|
52
|
+
const directory = this.getTempDir();
|
|
53
|
+
if (!fs.existsSync(directory)) {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
const entries = await fsPromises.readdir(directory);
|
|
57
|
+
for (let entry of entries) {
|
|
58
|
+
const repoCacheDirectory = path.join(directory, entry);
|
|
59
|
+
const stats = await fsPromises.lstat(repoCacheDirectory);
|
|
60
|
+
if (stats.isDirectory() && stats.ctimeMs < MAX_AGE && (!repoName || entry !== encodeFilename(repoName))) {
|
|
61
|
+
await fsPromises.rm(repoCacheDirectory, { recursive: true, force: true });
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
export function cached() {
|
|
67
|
+
return function (_target, _propertyKey, descriptor) {
|
|
68
|
+
const originalValue = descriptor.value;
|
|
69
|
+
descriptor.value = async function (...args) {
|
|
70
|
+
let files = CacheHolder.read(args[0], args[1]);
|
|
71
|
+
CacheHolder.clearOutdatedExcept(args[0]);
|
|
72
|
+
if (files == null) {
|
|
73
|
+
files = await originalValue.apply(this, args);
|
|
74
|
+
await CacheHolder.write(args[0], args[1], files);
|
|
75
|
+
}
|
|
76
|
+
return files;
|
|
77
|
+
};
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=cacheHolder.js.map
|
package/dist/i18nManager.js
CHANGED
|
@@ -2,6 +2,7 @@ import Comparator from "./annotations/comparator/comparator.js";
|
|
|
2
2
|
import AnnotationDiffStructureError from "./model/annotationDiffStructureError.js";
|
|
3
3
|
import { getUniqueName } from "./util/commonUtil.js";
|
|
4
4
|
import { join } from "path/posix"; // Ensure standardized dir separators to ensure Windows compatibility
|
|
5
|
+
import { slugify } from "transliteration";
|
|
5
6
|
// To generate keys, english language is more common, so compare all other
|
|
6
7
|
// languages with it
|
|
7
8
|
export class PropertyValue {
|
|
@@ -69,15 +70,17 @@ export class I18nFileContent {
|
|
|
69
70
|
const files = new Map();
|
|
70
71
|
if (this.hasTranslations()) {
|
|
71
72
|
this.properties.forEach((i18nLines, language) => {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
filename += "_" + language.i18n;
|
|
73
|
+
if (language.isDefault) {
|
|
74
|
+
createI18nFile("i18n", i18nLines);
|
|
75
75
|
}
|
|
76
|
-
|
|
77
|
-
files.set(filepath, [...i18nLines].map(([key, value]) => `${key}=${value}`).join("\n"));
|
|
76
|
+
createI18nFile("i18n_" + language.i18n, i18nLines);
|
|
78
77
|
});
|
|
79
78
|
}
|
|
80
79
|
return files;
|
|
80
|
+
function createI18nFile(filename, i18nLines) {
|
|
81
|
+
const filepath = join(i18nPathName, filename + ".properties");
|
|
82
|
+
files.set(filepath, [...i18nLines].map(([key, value]) => `${key}=${value}`).toSorted().join("\n"));
|
|
83
|
+
}
|
|
81
84
|
}
|
|
82
85
|
}
|
|
83
86
|
export default class I18nManager {
|
|
@@ -128,7 +131,7 @@ export default class I18nManager {
|
|
|
128
131
|
properties file again. And then compare with the next language and so on
|
|
129
132
|
and so on */
|
|
130
133
|
let defaultAnnotation = I18nManager.extractDefaultLanguageAnnotation(annotationJsons);
|
|
131
|
-
if (annotationJsons.size > 0
|
|
134
|
+
if (defaultAnnotation && annotationJsons.size > 0) {
|
|
132
135
|
defaultAnnotation = await this.populate([...annotationJsons], defaultAnnotation);
|
|
133
136
|
}
|
|
134
137
|
return defaultAnnotation;
|
|
@@ -152,7 +155,6 @@ export default class I18nManager {
|
|
|
152
155
|
return p;
|
|
153
156
|
}
|
|
154
157
|
static extractDefaultLanguageAnnotation(annotationJsons) {
|
|
155
|
-
let json = null;
|
|
156
158
|
for (const [language, json] of annotationJsons) {
|
|
157
159
|
if (language.isDefault) {
|
|
158
160
|
annotationJsons.delete(language);
|
|
@@ -160,7 +162,7 @@ export default class I18nManager {
|
|
|
160
162
|
}
|
|
161
163
|
}
|
|
162
164
|
const language = [...annotationJsons.keys()][0];
|
|
163
|
-
json = annotationJsons.get(language);
|
|
165
|
+
let json = annotationJsons.get(language);
|
|
164
166
|
annotationJsons.delete(language);
|
|
165
167
|
return { json, language };
|
|
166
168
|
}
|
|
@@ -188,7 +190,7 @@ export default class I18nManager {
|
|
|
188
190
|
if (typeof value !== "string") {
|
|
189
191
|
throw new Error("Failed to create unique key from: " + JSON.stringify(value));
|
|
190
192
|
}
|
|
191
|
-
const propertyName = value.replace(/\W/gi, "_")
|
|
193
|
+
const propertyName = slugify(value, { separator: "_", uppercase: true }).replace(/\W/gi, "_");
|
|
192
194
|
const key = getUniqueName([...this.existingKeys.keys()], propertyName);
|
|
193
195
|
this.existingKeys.add(key);
|
|
194
196
|
return key;
|
package/dist/index.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import * as dotenv from "dotenv";
|
|
2
2
|
import { logBetaUsage, logBuilderVersion } from "./util/commonUtil.js";
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
import
|
|
3
|
+
import AppVariant from "./appVariantManager.js";
|
|
4
|
+
import BaseApp from "./baseAppManager.js";
|
|
5
|
+
import I18nMerger from "./util/i18nMerger.js";
|
|
6
|
+
import ResourceUtil from "./util/resourceUtil.js";
|
|
6
7
|
import { determineProcessor } from "./processors/processor.js";
|
|
8
|
+
import FilesUtil from "./util/filesUtil.js";
|
|
7
9
|
/**
|
|
8
10
|
* Creates an appVariant bundle from the provided resources.
|
|
9
11
|
*/
|
|
@@ -13,12 +15,35 @@ export default ({ workspace, options, taskUtil }) => {
|
|
|
13
15
|
logBuilderVersion();
|
|
14
16
|
logBetaUsage();
|
|
15
17
|
const processor = determineProcessor(options.configuration);
|
|
16
|
-
const
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
18
|
+
const adaptationProject = await AppVariant.fromWorkspace(workspace, options.projectNamespace);
|
|
19
|
+
const appVariantIdHierarchy = await processor.getAppVariantIdHierarchy(adaptationProject.reference);
|
|
20
|
+
// appVariantIdHierarchy contains original application on bottom and the
|
|
21
|
+
// latest app variant on top. We reverse the list to process original
|
|
22
|
+
// application first and then app variants in chronological order.
|
|
23
|
+
const reversedHierarchy = appVariantIdHierarchy.toReversed();
|
|
24
|
+
const fetchFilesPromises = reversedHierarchy.map(({ repoName, cachebusterToken }) => processor.fetch(repoName, cachebusterToken));
|
|
25
|
+
fetchFilesPromises.push(Promise.resolve(adaptationProject.files));
|
|
26
|
+
const adapt = async (baseAppFiles, appVariantFiles) => {
|
|
27
|
+
const baseApp = BaseApp.fromFiles(baseAppFiles);
|
|
28
|
+
const appVariant = AppVariant.fromFiles(appVariantFiles);
|
|
29
|
+
const adaptedFiles = await baseApp.adapt(appVariant, processor);
|
|
30
|
+
return I18nMerger.merge(adaptedFiles, baseApp.i18nPath, appVariant);
|
|
31
|
+
};
|
|
32
|
+
let files = await fetchFilesPromises.reduce(async (previousFiles, currentFiles) => {
|
|
33
|
+
return adapt(await previousFiles, await currentFiles);
|
|
34
|
+
}, fetchFilesPromises.shift());
|
|
35
|
+
if (files) {
|
|
36
|
+
const references = appVariantIdHierarchy.map(item => item.appVariantId);
|
|
37
|
+
files = FilesUtil.filter(files);
|
|
38
|
+
files = FilesUtil.rename(files, references, adaptationProject.id);
|
|
39
|
+
adaptationProject.omitDeletedResources(files, options.projectNamespace, taskUtil);
|
|
40
|
+
const writePromises = new Array();
|
|
41
|
+
files.forEach((content, filename) => {
|
|
42
|
+
const resource = ResourceUtil.createResource(filename, options.projectNamespace, content);
|
|
43
|
+
writePromises.push(workspace.write(resource));
|
|
44
|
+
});
|
|
45
|
+
await Promise.all(writePromises);
|
|
46
|
+
}
|
|
22
47
|
}
|
|
23
48
|
return process(workspace, taskUtil);
|
|
24
49
|
};
|
package/dist/model/language.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
export default class Language {
|
|
2
|
-
sap: string;
|
|
3
|
-
i18n: string;
|
|
2
|
+
readonly sap: string;
|
|
3
|
+
readonly i18n: string;
|
|
4
4
|
isDefault: boolean;
|
|
5
|
-
constructor(sap: string, i18n: string);
|
|
5
|
+
constructor(sap: string, i18n: string, isDefault?: boolean);
|
|
6
6
|
/**
|
|
7
7
|
* Create a language array from languages in configuration and default language.
|
|
8
8
|
* @param languages Typically an array of objects. Probably could be undefined.
|
package/dist/model/language.js
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
|
+
const DEFAULT_LANGUAGE = "en";
|
|
1
2
|
export default class Language {
|
|
2
3
|
sap;
|
|
3
4
|
i18n;
|
|
4
5
|
isDefault;
|
|
5
|
-
constructor(sap, i18n) {
|
|
6
|
+
constructor(sap, i18n, isDefault = false) {
|
|
6
7
|
this.sap = sap;
|
|
7
8
|
this.i18n = i18n;
|
|
8
|
-
this.isDefault =
|
|
9
|
+
this.isDefault = isDefault;
|
|
9
10
|
}
|
|
10
11
|
/**
|
|
11
12
|
* Create a language array from languages in configuration and default language.
|
|
@@ -14,7 +15,6 @@ export default class Language {
|
|
|
14
15
|
* followed by the passed config languages.
|
|
15
16
|
*/
|
|
16
17
|
static create(languages) {
|
|
17
|
-
const defaultLanguage = new Language("", "");
|
|
18
18
|
let configLanguages = [];
|
|
19
19
|
if (languages !== undefined) {
|
|
20
20
|
configLanguages = languages.map(item => {
|
|
@@ -30,7 +30,14 @@ export default class Language {
|
|
|
30
30
|
}
|
|
31
31
|
});
|
|
32
32
|
}
|
|
33
|
-
|
|
33
|
+
let defaultLanguage = configLanguages.find(language => language.sap.toLowerCase() === DEFAULT_LANGUAGE) ?? configLanguages[0];
|
|
34
|
+
if (defaultLanguage) {
|
|
35
|
+
defaultLanguage.isDefault = true;
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
return [new Language(DEFAULT_LANGUAGE.toUpperCase(), DEFAULT_LANGUAGE, true), ...configLanguages];
|
|
39
|
+
}
|
|
40
|
+
return configLanguages;
|
|
34
41
|
}
|
|
35
42
|
;
|
|
36
43
|
}
|
package/dist/model/types.d.ts
CHANGED
|
@@ -8,7 +8,7 @@ export interface ICreateServiceInstanceParams {
|
|
|
8
8
|
spaceGuid: string;
|
|
9
9
|
planName: string;
|
|
10
10
|
serviceName: string;
|
|
11
|
-
serviceInstanceName
|
|
11
|
+
serviceInstanceName: string;
|
|
12
12
|
tags: string[];
|
|
13
13
|
parameters?: any;
|
|
14
14
|
}
|
|
@@ -60,11 +60,13 @@ export interface IChange {
|
|
|
60
60
|
texts?: IChangeText;
|
|
61
61
|
layer?: string;
|
|
62
62
|
content?: IChangeContent;
|
|
63
|
+
filename: string;
|
|
63
64
|
}
|
|
64
65
|
export interface IChangeText {
|
|
65
66
|
i18n: string;
|
|
66
67
|
}
|
|
67
68
|
export interface IChangeContent {
|
|
69
|
+
dataSource?: any;
|
|
68
70
|
bundleUrl?: string;
|
|
69
71
|
fallbackLocale?: string;
|
|
70
72
|
modelId?: string;
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import AbapRepoManager from "../repositories/abapRepoManager.js";
|
|
2
2
|
import AnnotationManager from "../annotationManager.js";
|
|
3
|
-
import
|
|
3
|
+
import IAppVariantIdHierarchyItem from "../model/appVariantIdHierarchyItem.js";
|
|
4
4
|
import { IConfiguration } from "../model/types.js";
|
|
5
5
|
import IProcessor from "./processor.js";
|
|
6
6
|
export default class AbapProcessor implements IProcessor {
|
|
7
7
|
private abapRepoManager;
|
|
8
8
|
private configuration;
|
|
9
|
-
private cacheManager;
|
|
10
9
|
private annotationManager;
|
|
11
|
-
constructor(configuration: IConfiguration,
|
|
12
|
-
|
|
10
|
+
constructor(configuration: IConfiguration, abapRepoManager: AbapRepoManager, annotationManager: AnnotationManager);
|
|
11
|
+
getAppVariantIdHierarchy(appId: string): Promise<IAppVariantIdHierarchyItem[]>;
|
|
12
|
+
fetch(repoName: string, _cachebusterToken: string): Promise<Map<string, string>>;
|
|
13
13
|
validateConfiguration(): void;
|
|
14
|
-
updateLandscapeSpecificContent(
|
|
14
|
+
updateLandscapeSpecificContent(baseAppManifest: any, baseAppFiles: Map<string, string>, appVariantId: string): Promise<void>;
|
|
15
15
|
getConfigurationType(): string;
|
|
16
16
|
createAppVariantHierarchyItem(appVariantId: string, version: string): {
|
|
17
17
|
appVariantId: string;
|
|
@@ -1,26 +1,35 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
1
7
|
import Language from "../model/language.js";
|
|
8
|
+
import { cached } from "../cache/cacheHolder.js";
|
|
2
9
|
import { validateObject } from "../util/commonUtil.js";
|
|
3
10
|
export default class AbapProcessor {
|
|
4
11
|
abapRepoManager;
|
|
5
12
|
configuration;
|
|
6
|
-
cacheManager;
|
|
7
13
|
annotationManager;
|
|
8
|
-
constructor(configuration,
|
|
14
|
+
constructor(configuration, abapRepoManager, annotationManager) {
|
|
9
15
|
this.configuration = configuration;
|
|
10
16
|
this.abapRepoManager = abapRepoManager;
|
|
11
|
-
this.cacheManager = cacheManager;
|
|
12
17
|
this.annotationManager = annotationManager;
|
|
13
18
|
}
|
|
14
|
-
|
|
15
|
-
return this.
|
|
19
|
+
getAppVariantIdHierarchy(appId) {
|
|
20
|
+
return this.abapRepoManager.getAppVariantIdHierarchy(appId);
|
|
21
|
+
}
|
|
22
|
+
fetch(repoName, _cachebusterToken) {
|
|
23
|
+
return this.abapRepoManager.fetch(repoName);
|
|
16
24
|
}
|
|
17
25
|
validateConfiguration() {
|
|
18
26
|
// validate general app config
|
|
19
27
|
const properties = ["appName"];
|
|
20
28
|
validateObject(this.configuration, properties, "should be specified in ui5.yaml configuration");
|
|
21
29
|
}
|
|
22
|
-
async updateLandscapeSpecificContent(
|
|
23
|
-
const
|
|
30
|
+
async updateLandscapeSpecificContent(baseAppManifest, baseAppFiles, appVariantId) {
|
|
31
|
+
const languages = Language.create(this.configuration.languages);
|
|
32
|
+
const files = await this.annotationManager.process(baseAppManifest, languages, appVariantId);
|
|
24
33
|
if (baseAppFiles) {
|
|
25
34
|
files.forEach((value, key) => baseAppFiles.set(key, value));
|
|
26
35
|
}
|
|
@@ -36,4 +45,7 @@ export default class AbapProcessor {
|
|
|
36
45
|
};
|
|
37
46
|
}
|
|
38
47
|
}
|
|
48
|
+
__decorate([
|
|
49
|
+
cached()
|
|
50
|
+
], AbapProcessor.prototype, "fetch", null);
|
|
39
51
|
//# sourceMappingURL=abapProcessor.js.map
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import
|
|
1
|
+
import IAppInfo from "../model/appVariantIdHierarchyItem.js";
|
|
2
2
|
import { IConfiguration } from "../model/types.js";
|
|
3
3
|
import IProcessor from "./processor.js";
|
|
4
4
|
export default class CFProcessor implements IProcessor {
|
|
5
5
|
private configuration;
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
constructor(configuration: IConfiguration);
|
|
7
|
+
getAppVariantIdHierarchy(appId: string): Promise<IAppInfo[]>;
|
|
8
|
+
fetch(_repoName: string, _cachebusterToken: string): Promise<Map<string, string>>;
|
|
9
9
|
validateConfiguration(): void;
|
|
10
10
|
updateLandscapeSpecificContent(renamedBaseAppManifest: any): Promise<void>;
|
|
11
11
|
private updateCloudPlatform;
|
|
@@ -1,14 +1,27 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
1
7
|
import HTML5RepoManager from "../repositories/html5RepoManager.js";
|
|
8
|
+
import { cached } from "../cache/cacheHolder.js";
|
|
2
9
|
import { validateObject } from "../util/commonUtil.js";
|
|
3
10
|
export default class CFProcessor {
|
|
4
11
|
configuration;
|
|
5
|
-
|
|
6
|
-
constructor(configuration, cacheManager) {
|
|
12
|
+
constructor(configuration) {
|
|
7
13
|
this.configuration = configuration;
|
|
8
|
-
this.cacheManager = cacheManager;
|
|
9
14
|
}
|
|
10
|
-
async
|
|
11
|
-
|
|
15
|
+
async getAppVariantIdHierarchy(appId) {
|
|
16
|
+
const metadata = await HTML5RepoManager.getMetadata(this.configuration);
|
|
17
|
+
return [{
|
|
18
|
+
repoName: this.configuration.appName,
|
|
19
|
+
appVariantId: appId,
|
|
20
|
+
cachebusterToken: metadata.changedOn
|
|
21
|
+
}];
|
|
22
|
+
}
|
|
23
|
+
fetch(_repoName, _cachebusterToken) {
|
|
24
|
+
return HTML5RepoManager.getBaseAppFiles(this.configuration);
|
|
12
25
|
}
|
|
13
26
|
validateConfiguration() {
|
|
14
27
|
validateObject(this.configuration, ["appHostId", "appName", "appVersion"], "should be specified in ui5.yaml configuration");
|
|
@@ -16,20 +29,20 @@ export default class CFProcessor {
|
|
|
16
29
|
async updateLandscapeSpecificContent(renamedBaseAppManifest) {
|
|
17
30
|
this.updateCloudPlatform(renamedBaseAppManifest);
|
|
18
31
|
}
|
|
19
|
-
updateCloudPlatform(
|
|
20
|
-
const sapCloudService =
|
|
21
|
-
const sapPlatformCf =
|
|
22
|
-
if (sapPlatformCf && sapCloudService) {
|
|
32
|
+
updateCloudPlatform(baseAppManifest) {
|
|
33
|
+
const sapCloudService = baseAppManifest["sap.cloud"]?.service;
|
|
34
|
+
const sapPlatformCf = baseAppManifest["sap.platform.cf"];
|
|
35
|
+
if (sapPlatformCf?.oAuthScopes && sapCloudService) {
|
|
23
36
|
sapPlatformCf.oAuthScopes = sapPlatformCf.oAuthScopes.map((scope) => scope.replace(`$XSAPPNAME.`, `$XSAPPNAME('${sapCloudService}').`));
|
|
24
37
|
}
|
|
25
38
|
if (this.configuration.sapCloudService) {
|
|
26
|
-
if (
|
|
27
|
-
|
|
39
|
+
if (baseAppManifest["sap.cloud"] == null) {
|
|
40
|
+
baseAppManifest["sap.cloud"] = {};
|
|
28
41
|
}
|
|
29
|
-
|
|
42
|
+
baseAppManifest["sap.cloud"].service = this.configuration.sapCloudService;
|
|
30
43
|
}
|
|
31
44
|
else {
|
|
32
|
-
delete
|
|
45
|
+
delete baseAppManifest["sap.cloud"];
|
|
33
46
|
}
|
|
34
47
|
}
|
|
35
48
|
getConfigurationType() {
|
|
@@ -42,4 +55,7 @@ export default class CFProcessor {
|
|
|
42
55
|
};
|
|
43
56
|
}
|
|
44
57
|
}
|
|
58
|
+
__decorate([
|
|
59
|
+
cached()
|
|
60
|
+
], CFProcessor.prototype, "fetch", null);
|
|
45
61
|
//# sourceMappingURL=cfProcessor.js.map
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
import IAppVariantIdHierarchyItem from "../model/appVariantIdHierarchyItem.js";
|
|
1
2
|
import { IConfiguration } from "../model/types.js";
|
|
2
3
|
export default interface IProcessor {
|
|
4
|
+
getAppVariantIdHierarchy(appId: string): Promise<IAppVariantIdHierarchyItem[]>;
|
|
5
|
+
fetch(repoName: string, cachebusterToken: string): Promise<Map<string, string>>;
|
|
3
6
|
createAppVariantHierarchyItem(appVariantId: string, version: string): void;
|
|
4
|
-
|
|
5
|
-
updateLandscapeSpecificContent(renamedBaseAppManifest: any, baseAppFiles?: Map<string, string>): Promise<void>;
|
|
7
|
+
updateLandscapeSpecificContent(baseAppManifest: any, baseAppFiles: ReadonlyMap<string, string>, appVariantId: string): Promise<void>;
|
|
6
8
|
}
|
|
7
9
|
export declare function determineProcessor(configuration: IConfiguration): IProcessor;
|
|
@@ -1,15 +1,13 @@
|
|
|
1
1
|
import AbapProcessor from "./abapProcessor.js";
|
|
2
2
|
import AbapRepoManager from "../repositories/abapRepoManager.js";
|
|
3
3
|
import AnnotationManager from "../annotationManager.js";
|
|
4
|
-
import BaseAppFilesCacheManager from "../cache/baseAppFilesCacheManager.js";
|
|
5
4
|
import CFProcessor from "./cfProcessor.js";
|
|
6
5
|
export function determineProcessor(configuration) {
|
|
7
|
-
const cacheManager = new BaseAppFilesCacheManager(configuration);
|
|
8
6
|
const abapRepoManager = new AbapRepoManager(configuration);
|
|
9
7
|
const annotationManager = new AnnotationManager(configuration, abapRepoManager);
|
|
10
8
|
const processors = [
|
|
11
|
-
new CFProcessor(configuration
|
|
12
|
-
new AbapProcessor(configuration,
|
|
9
|
+
new CFProcessor(configuration),
|
|
10
|
+
new AbapProcessor(configuration, abapRepoManager, annotationManager)
|
|
13
11
|
];
|
|
14
12
|
let processor = processors.find(processor => processor.getConfigurationType() === configuration.type);
|
|
15
13
|
if (processor) {
|
|
@@ -22,7 +20,7 @@ export function determineProcessor(configuration) {
|
|
|
22
20
|
processor.validateConfiguration();
|
|
23
21
|
return processor;
|
|
24
22
|
}
|
|
25
|
-
catch (
|
|
23
|
+
catch (_error) {
|
|
26
24
|
continue;
|
|
27
25
|
}
|
|
28
26
|
}
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import { IConfiguration, IMetadata } from "../model/types.js";
|
|
2
2
|
import AbapProvider from "./abapProvider.js";
|
|
3
|
+
import IAppVariantIdHierarchyItem from "../model/appVariantIdHierarchyItem.js";
|
|
3
4
|
export default class AbapRepoManager {
|
|
4
5
|
private configuration;
|
|
5
6
|
private abapProvider;
|
|
6
7
|
constructor(configuration: IConfiguration, abapProvider?: AbapProvider);
|
|
8
|
+
getAppVariantIdHierarchy(id: string): Promise<IAppVariantIdHierarchyItem[]>;
|
|
7
9
|
getAnnotationMetadata(uri: string): Promise<IMetadata>;
|
|
8
10
|
downloadAnnotationFile(uri: string): Promise<Map<string, any>>;
|
|
9
11
|
getMetadata(id: string): Promise<IMetadata>;
|
|
10
|
-
|
|
12
|
+
fetch(repoName: string): Promise<Map<string, string>>;
|
|
11
13
|
}
|
|
@@ -20,6 +20,26 @@ export default class AbapRepoManager {
|
|
|
20
20
|
this.configuration = configuration;
|
|
21
21
|
this.abapProvider = abapProvider ? abapProvider : new AbapProvider();
|
|
22
22
|
}
|
|
23
|
+
async getAppVariantIdHierarchy(id) {
|
|
24
|
+
const provider = await this.abapProvider.get(this.configuration);
|
|
25
|
+
const lrep = provider.getLayeredRepository();
|
|
26
|
+
const response = await lrep.get("/dta_folder/app_info", {
|
|
27
|
+
params: { id }
|
|
28
|
+
});
|
|
29
|
+
if (response.status === 200) {
|
|
30
|
+
return JSON.parse(response.data)?.appVariantIdHierarchy;
|
|
31
|
+
}
|
|
32
|
+
else if (this.configuration.appName) {
|
|
33
|
+
// Fallback to old API on old ABAP backend or CF for backward compatibility
|
|
34
|
+
const metadataResponse = await this.getMetadata(id);
|
|
35
|
+
return [{
|
|
36
|
+
repoName: this.configuration.appName,
|
|
37
|
+
appVariantId: id,
|
|
38
|
+
cachebusterToken: metadataResponse.changedOn
|
|
39
|
+
}];
|
|
40
|
+
}
|
|
41
|
+
throw new Error(`App variant id hierarchy for app id '${id}' is not provided`);
|
|
42
|
+
}
|
|
23
43
|
async getAnnotationMetadata(uri) {
|
|
24
44
|
const provider = await this.abapProvider.get(this.configuration);
|
|
25
45
|
const response = await provider.head(uri);
|
|
@@ -48,12 +68,11 @@ export default class AbapRepoManager {
|
|
|
48
68
|
id
|
|
49
69
|
};
|
|
50
70
|
}
|
|
51
|
-
async
|
|
52
|
-
const
|
|
53
|
-
const encodedAppName = encodeURIComponent(appName);
|
|
71
|
+
async fetch(repoName) {
|
|
72
|
+
const encodedRepoName = encodeURIComponent(repoName);
|
|
54
73
|
const provider = await this.abapProvider.get(this.configuration);
|
|
55
74
|
const ui5Repo = provider.getUi5AbapRepository();
|
|
56
|
-
const response = await ui5Repo.get(`/Repositories('${
|
|
75
|
+
const response = await ui5Repo.get(`/Repositories('${encodedRepoName}')`, {
|
|
57
76
|
params: {
|
|
58
77
|
DownloadFiles: "RUNTIME",
|
|
59
78
|
CodePage: "UTF8",
|
|
@@ -65,7 +84,7 @@ export default class AbapRepoManager {
|
|
|
65
84
|
const buffer = Buffer.from(data.d.ZipArchive, "base64");
|
|
66
85
|
return unzipZipEntries(buffer);
|
|
67
86
|
}
|
|
68
|
-
throw new Error(`App '${
|
|
87
|
+
throw new Error(`App '${repoName}' doesn't contain files`);
|
|
69
88
|
}
|
|
70
89
|
}
|
|
71
90
|
//# sourceMappingURL=abapRepoManager.js.map
|
|
@@ -13,7 +13,7 @@ export default class HTML5RepoManager {
|
|
|
13
13
|
return this.requestMetadata(configuration, baseUri, token);
|
|
14
14
|
}
|
|
15
15
|
static async getHtml5RepoInfo(configuration) {
|
|
16
|
-
const spaceGuid = await CFUtil.getSpaceGuid(configuration?.
|
|
16
|
+
const spaceGuid = await CFUtil.getSpaceGuid(configuration?.space);
|
|
17
17
|
const credentials = await this.getHTML5Credentials(spaceGuid);
|
|
18
18
|
const token = await this.getToken(credentials);
|
|
19
19
|
return {
|
|
@@ -33,7 +33,8 @@ export default class HTML5RepoManager {
|
|
|
33
33
|
const createParams = {
|
|
34
34
|
spaceGuid,
|
|
35
35
|
planName: PLAN_NAME,
|
|
36
|
-
serviceName:
|
|
36
|
+
serviceName: "html5-apps-repo",
|
|
37
|
+
serviceInstanceName: SERVIСE_INSTANCE_NAME,
|
|
37
38
|
tags: ["html5-apps-repo-rt"]
|
|
38
39
|
};
|
|
39
40
|
const serviceKeys = await CFUtil.getServiceInstanceKeys(getParams, createParams);
|
package/dist/util/cfUtil.d.ts
CHANGED
|
@@ -14,6 +14,7 @@ export default class CFUtil {
|
|
|
14
14
|
private static getServiceKeys;
|
|
15
15
|
private static createServiceKey;
|
|
16
16
|
private static getServiceInstance;
|
|
17
|
+
static processErrors(json: any): void;
|
|
17
18
|
static requestCfApi(url: string): Promise<IResource[]>;
|
|
18
19
|
static getOAuthToken(): Promise<string>;
|
|
19
20
|
private static cfExecute;
|