@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.
Files changed (70) hide show
  1. package/CHANGELOG.md +16 -1
  2. package/README.md +16 -12
  3. package/REUSE.toml +10 -0
  4. package/dist/annotationManager.d.ts +1 -1
  5. package/dist/annotationManager.js +5 -8
  6. package/dist/annotations/dataSource/dataSource.js +0 -1
  7. package/dist/annotations/serviceRequestor.js +3 -15
  8. package/dist/appVariantManager.d.ts +16 -11
  9. package/dist/appVariantManager.js +56 -83
  10. package/dist/baseAppManager.d.ts +16 -16
  11. package/dist/baseAppManager.js +58 -81
  12. package/dist/bundle.d.ts +2 -3
  13. package/dist/bundle.js +3834 -3490
  14. package/dist/cache/cacheHolder.d.ts +18 -0
  15. package/dist/cache/cacheHolder.js +80 -0
  16. package/dist/i18nManager.js +11 -9
  17. package/dist/index.js +34 -9
  18. package/dist/model/appVariantIdHierarchyItem.d.ts +5 -0
  19. package/dist/model/appVariantIdHierarchyItem.js +2 -0
  20. package/dist/model/configuration.d.ts +2 -2
  21. package/dist/model/language.d.ts +3 -3
  22. package/dist/model/language.js +11 -4
  23. package/dist/model/types.d.ts +3 -1
  24. package/dist/processors/abapProcessor.d.ts +5 -5
  25. package/dist/processors/abapProcessor.js +19 -7
  26. package/dist/processors/cfProcessor.d.ts +4 -4
  27. package/dist/processors/cfProcessor.js +29 -13
  28. package/dist/processors/processor.d.ts +4 -2
  29. package/dist/processors/processor.js +3 -5
  30. package/dist/repositories/abapRepoManager.d.ts +3 -1
  31. package/dist/repositories/abapRepoManager.js +24 -5
  32. package/dist/repositories/html5RepoManager.js +3 -2
  33. package/dist/util/cfUtil.d.ts +1 -0
  34. package/dist/util/cfUtil.js +27 -23
  35. package/dist/util/commonUtil.d.ts +5 -3
  36. package/dist/util/commonUtil.js +104 -31
  37. package/dist/util/filesUtil.d.ts +17 -0
  38. package/dist/util/filesUtil.js +49 -0
  39. package/dist/util/i18nMerger.d.ts +15 -20
  40. package/dist/util/i18nMerger.js +46 -64
  41. package/dist/util/renamingHandlers/manifestHandler.d.ts +6 -0
  42. package/dist/util/renamingHandlers/manifestHandler.js +20 -0
  43. package/dist/util/renamingHandlers/renamingHandler.d.ts +4 -0
  44. package/dist/util/renamingHandlers/renamingHandler.js +2 -0
  45. package/dist/util/requestUtil.d.ts +2 -1
  46. package/dist/util/resourceUtil.d.ts +3 -1
  47. package/dist/util/resourceUtil.js +15 -2
  48. package/eslint.config.js +20 -4
  49. package/package.json +28 -22
  50. package/scripts/rollup/bundle.d.ts +2 -3
  51. package/scripts/rollup/bundleDefinition.js +2 -2
  52. package/scripts/rollup/overrides/sap/ui/fl/Utils.js +13 -0
  53. package/scripts/rollup/overrides/sap/ui/fl/apply/_internal/changes/FlexCustomData.js +13 -0
  54. package/scripts/rollup/overrides/sap/ui/fl/apply/_internal/flexObjects/AnnotationChange.js +11 -0
  55. package/scripts/rollup/overrides/sap/ui/fl/apply/_internal/flexObjects/AppDescriptorChange.js +68 -0
  56. package/scripts/rollup/overrides/sap/ui/fl/apply/_internal/flexObjects/VariantChange.js +11 -0
  57. package/scripts/rollup/overrides/sap/ui/fl/apply/_internal/flexObjects/VariantManagementChange.js +11 -0
  58. package/scripts/rollup/overrides/sap/ui/fl/apply/_internal/flexState/controlVariants/VariantManagementState.js +13 -0
  59. package/scripts/rollup/overrides/sap/ui/fl/initial/_internal/changeHandlers/ChangeHandlerRegistration.js +13 -0
  60. package/scripts/rollup/overrides/sap/ui/fl/initial/_internal/changeHandlers/ChangeHandlerStorage.js +14 -0
  61. package/scripts/rollup/project/ui5.yaml +1 -1
  62. package/scripts/test-integration-prep.sh +4 -0
  63. package/types/ui5.d.ts +10 -0
  64. package/dist/cache/annotationsCacheManager.d.ts +0 -8
  65. package/dist/cache/annotationsCacheManager.js +0 -16
  66. package/dist/cache/baseAppFilesCacheManager.d.ts +0 -6
  67. package/dist/cache/baseAppFilesCacheManager.js +0 -12
  68. package/dist/cache/cacheManager.d.ts +0 -16
  69. package/dist/cache/cacheManager.js +0 -65
  70. 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
@@ -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
- let filename = "i18n";
73
- if (language.i18n) {
74
- filename += "_" + language.i18n;
73
+ if (language.isDefault) {
74
+ createI18nFile("i18n", i18nLines);
75
75
  }
76
- const filepath = join(i18nPathName, filename + ".properties");
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 && defaultAnnotation) {
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, "_").toUpperCase();
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 AppVariantManager from "./appVariantManager.js";
4
- import BaseAppManager from "./baseAppManager.js";
5
- import I18NMerger from "./util/i18nMerger.js";
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 appVariantResources = await AppVariantManager.getAppVariantResourcesToProcess(workspace);
17
- const appVariantInfo = await AppVariantManager.process(appVariantResources, options.projectNamespace, taskUtil);
18
- const baseAppFiles = await processor.getBaseAppFiles(appVariantInfo.reference);
19
- const { resources, manifestInfo } = await BaseAppManager.process(baseAppFiles, appVariantInfo, options, processor);
20
- const mergedResources = await I18NMerger.mergeI18NFiles(resources, appVariantResources, options.projectNamespace, manifestInfo.i18nPath, appVariantInfo, taskUtil);
21
- await Promise.all(mergedResources.map(resource => workspace.write(resource)));
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
  };
@@ -0,0 +1,5 @@
1
+ export default interface IAppVariantIdHierarchyItem {
2
+ appVariantId: string;
3
+ repoName: string;
4
+ cachebusterToken: string;
5
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=appVariantIdHierarchyItem.js.map
@@ -4,8 +4,8 @@ export interface IConfiguration {
4
4
  appId?: string;
5
5
  appName?: string;
6
6
  appVersion?: string;
7
- spaceGuid?: string;
8
- orgGuid?: string;
7
+ space?: string;
8
+ org?: string;
9
9
  sapCloudService?: string;
10
10
  destination?: string;
11
11
  type?: "cf" | "abap";
@@ -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.
@@ -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 = sap === "";
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
- return [defaultLanguage, ...configLanguages];
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
  }
@@ -8,7 +8,7 @@ export interface ICreateServiceInstanceParams {
8
8
  spaceGuid: string;
9
9
  planName: string;
10
10
  serviceName: string;
11
- serviceInstanceName?: string;
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 BaseAppFilesCacheManager from "../cache/baseAppFilesCacheManager.js";
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, cacheManager: BaseAppFilesCacheManager, abapRepoManager: AbapRepoManager, annotationManager: AnnotationManager);
12
- getBaseAppFiles(baseAppId: string): Promise<Map<string, string>>;
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(renamedBaseAppManifest: any, baseAppFiles?: Map<string, string>): Promise<void>;
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, cacheManager, abapRepoManager, annotationManager) {
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
- getBaseAppFiles(baseAppId) {
15
- return this.cacheManager.getFiles(() => this.abapRepoManager.getMetadata(baseAppId), () => this.abapRepoManager.downloadBaseAppFiles());
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(renamedBaseAppManifest, baseAppFiles) {
23
- const files = await this.annotationManager.process(renamedBaseAppManifest, (Language.create(this.configuration.languages)));
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 BaseAppFilesCacheManager from "../cache/baseAppFilesCacheManager.js";
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
- private cacheManager;
7
- constructor(configuration: IConfiguration, cacheManager: BaseAppFilesCacheManager);
8
- getBaseAppFiles(): Promise<Map<string, string>>;
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
- cacheManager;
6
- constructor(configuration, cacheManager) {
12
+ constructor(configuration) {
7
13
  this.configuration = configuration;
8
- this.cacheManager = cacheManager;
9
14
  }
10
- async getBaseAppFiles() {
11
- return this.cacheManager.getFiles(() => HTML5RepoManager.getMetadata(this.configuration), () => HTML5RepoManager.getBaseAppFiles(this.configuration));
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(renamedBaseAppManifest) {
20
- const sapCloudService = renamedBaseAppManifest["sap.cloud"]?.service;
21
- const sapPlatformCf = renamedBaseAppManifest["sap.platform.cf"];
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 (renamedBaseAppManifest["sap.cloud"] == null) {
27
- renamedBaseAppManifest["sap.cloud"] = {};
39
+ if (baseAppManifest["sap.cloud"] == null) {
40
+ baseAppManifest["sap.cloud"] = {};
28
41
  }
29
- renamedBaseAppManifest["sap.cloud"].service = this.configuration.sapCloudService;
42
+ baseAppManifest["sap.cloud"].service = this.configuration.sapCloudService;
30
43
  }
31
44
  else {
32
- delete renamedBaseAppManifest["sap.cloud"];
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
- getBaseAppFiles(baseAppId: string): Promise<Map<string, string>>;
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, cacheManager),
12
- new AbapProcessor(configuration, cacheManager, abapRepoManager, annotationManager)
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 (error) {
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
- downloadBaseAppFiles(): Promise<Map<string, string>>;
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 downloadBaseAppFiles() {
52
- const { destination, appName } = this.configuration;
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('${encodedAppName}')`, {
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 '${appName}' from '${destination}' doesn't contain files`);
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?.spaceGuid);
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: SERVIСE_INSTANCE_NAME,
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);
@@ -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;