@ui5/task-adaptation 1.6.7 → 1.7.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 (74) hide show
  1. package/.github/workflows/codeql.yml +35 -0
  2. package/.github/workflows/release-please.yml +53 -0
  3. package/.release-please-manifest.json +3 -0
  4. package/CHANGELOG.md +42 -36
  5. package/dist/adapters/abapAdapter.d.ts +3 -3
  6. package/dist/adapters/abapAdapter.js +19 -8
  7. package/dist/adapters/adapter.d.ts +3 -2
  8. package/dist/adapters/adapter.js +9 -3
  9. package/dist/adapters/cfAdapter.d.ts +2 -2
  10. package/dist/adapters/cfAdapter.js +12 -12
  11. package/dist/adapters/commands/command.js +0 -27
  12. package/dist/adapters/commands/downloadAnnotationsCommand.d.ts +3 -4
  13. package/dist/adapters/commands/downloadAnnotationsCommand.js +4 -4
  14. package/dist/adapters/commands/fetchPreviewResourcesCommand.js +1 -1
  15. package/dist/adapters/commands/omitDeletedResourcesCommand.d.ts +1 -1
  16. package/dist/adapters/commands/renameFilesCommand.d.ts +0 -22
  17. package/dist/adapters/commands/renameFilesCommand.js +2 -114
  18. package/dist/adapters/commands/renameManifestCommand.js +2 -2
  19. package/dist/adapters/previewAdapter.d.ts +2 -2
  20. package/dist/adapters/previewAdapter.js +4 -4
  21. package/dist/annotations/abapAnnotationManager.js +1 -3
  22. package/dist/annotations/dataSource/dataSource.d.ts +6 -5
  23. package/dist/annotations/dataSource/dataSource.js +36 -12
  24. package/dist/annotations/dataSource/dataSourceManager.d.ts +2 -2
  25. package/dist/annotations/dataSource/dataSourceManager.js +2 -2
  26. package/dist/annotations/dataSource/dataSourceOData.d.ts +2 -2
  27. package/dist/annotations/transformers/transformer.d.ts +2 -2
  28. package/dist/annotations/transformers/traverseReferences.d.ts +1 -1
  29. package/dist/annotations/transformers/traverseReferences.js +2 -2
  30. package/dist/appVariant.d.ts +5 -7
  31. package/dist/appVariant.js +9 -23
  32. package/dist/baseApp.d.ts +1 -0
  33. package/dist/baseApp.js +10 -0
  34. package/dist/bundle.js +86 -53
  35. package/dist/cache/cacheHolder.d.ts +6 -12
  36. package/dist/cache/cacheHolder.js +27 -39
  37. package/dist/cache/cachedResource.d.ts +2 -1
  38. package/dist/index.d.ts +6 -7
  39. package/dist/index.js +49 -42
  40. package/dist/landscapeConfiguration.d.ts +4 -4
  41. package/dist/landscapeConfiguration.js +48 -44
  42. package/dist/model/configuration.d.ts +0 -1
  43. package/dist/model/types.d.ts +1 -3
  44. package/dist/repositories/abapRepository.d.ts +1 -1
  45. package/dist/repositories/abapRepository.js +3 -3
  46. package/dist/repositories/cacheRepository.d.ts +4 -5
  47. package/dist/repositories/cacheRepository.js +10 -18
  48. package/dist/repositories/html5Repository.d.ts +1 -1
  49. package/dist/repositories/html5Repository.js +2 -2
  50. package/dist/repositories/localRepository.d.ts +1 -1
  51. package/dist/repositories/localRepository.js +2 -2
  52. package/dist/repositories/repository.d.ts +1 -1
  53. package/dist/util/cfUtil.d.ts +6 -24
  54. package/dist/util/cfUtil.js +36 -93
  55. package/dist/util/commonUtil.d.ts +1 -9
  56. package/dist/util/commonUtil.js +27 -29
  57. package/dist/util/fsUtil.js +1 -2
  58. package/dist/util/movingHandler/changeFileMoveHandler.d.ts +1 -0
  59. package/dist/util/movingHandler/changeFileMoveHandler.js +11 -3
  60. package/dist/util/referencesBuilder.d.ts +15 -0
  61. package/dist/util/referencesBuilder.js +35 -0
  62. package/dist/util/renaming/fileRenamer.d.ts +23 -0
  63. package/dist/util/renaming/fileRenamer.js +120 -0
  64. package/dist/util/{renamingHandlers → renaming/handlers}/jsonRenamingHandler.d.ts +0 -2
  65. package/dist/util/{renamingHandlers → renaming/handlers}/jsonRenamingHandler.js +0 -6
  66. package/dist/util/{renamingUtil.d.ts → renaming/referenceRenaming.d.ts} +4 -4
  67. package/dist/util/{renamingUtil.js → renaming/referenceRenaming.js} +8 -8
  68. package/dist/util/resourceUtil.js +6 -2
  69. package/package.json +11 -4
  70. package/release-please-config.json +66 -0
  71. package/dist/annotations/serviceRequestor.d.ts +0 -9
  72. package/dist/annotations/serviceRequestor.js +0 -62
  73. /package/dist/util/{renamingHandlers → renaming/handlers}/manifestRenamingHandler.d.ts +0 -0
  74. /package/dist/util/{renamingHandlers → renaming/handlers}/manifestRenamingHandler.js +0 -0
@@ -1,19 +1,5 @@
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
- };
7
- import ManifestRenamingHandler from "../../util/renamingHandlers/manifestRenamingHandler.js";
8
- import { stringToBuffer, bufferToString, bufferToJson, jsonToBuffer } from "../../util/commonUtil.js";
9
- import { getSAPUI5DependencyIds } from "../../util/manifestUtil.js";
10
- import { renameMap } from "../../util/renamingUtil.js";
11
- import { TEXT_EXTENSIONS } from "../../util/resourceUtil.js";
12
- import { posix as path } from "path";
1
+ import FileRenamer from "../../util/renaming/fileRenamer.js";
13
2
  import { PostCommand } from "./command.js";
14
- function isTextFile(filename) {
15
- return TEXT_EXTENSIONS.has(path.extname(filename).slice(1));
16
- }
17
3
  export default class RenameFilesCommand extends PostCommand {
18
4
  references;
19
5
  constructor(references) {
@@ -21,105 +7,7 @@ export default class RenameFilesCommand extends PostCommand {
21
7
  this.references = references;
22
8
  }
23
9
  async execute(files) {
24
- this.rename(files, this.references);
25
- }
26
- /**
27
- * 1p. i18n.properties are not renamed and property keys are ignored during
28
- * the renaming across the files.
29
- * @param files - all files both base and appVariants
30
- * @param references - Reference maps of the app variant
31
- * @returns A map of renamed files
32
- */
33
- rename(files, references) {
34
- const IGNORE_EXTENSIONS = [".properties"];
35
- const ignoreInString = [
36
- ...this.getI18nPropertyKeys(files),
37
- ...this.getManifestSAPUI5DependencyIds(files)
38
- ];
39
- const updates = new Map();
40
- for (const [filename, content] of files) {
41
- if (!isTextFile(filename)) {
42
- continue;
43
- }
44
- if (!IGNORE_EXTENSIONS.some(ext => filename.endsWith(ext))) {
45
- // 5p. We pass replacements as ignores since we don't want to
46
- // rename them again. E.g. we replace app.id with
47
- // customer.app.id, but if we found customer.app.id somewhere,
48
- // because we applied changes or something, we don't want to
49
- // rename it again to customer.customer.app.id.
50
- const renamed = renameMap(bufferToString(content), references, [...references.values(), ...ignoreInString]);
51
- updates.set(filename, stringToBuffer(renamed));
52
- }
53
- }
54
- for (const [filename, content] of updates) {
55
- files.set(filename, content);
56
- }
57
- }
58
- getManifestSAPUI5DependencyIds(files) {
59
- const manifestFile = files.get("manifest.json");
60
- return manifestFile ? getSAPUI5DependencyIds(bufferToJson(manifestFile)) : [];
61
- }
62
- getI18nPropertyKeys(files) {
63
- const keys = new Set();
64
- files.forEach((content, filename) => {
65
- if (filename.endsWith(".properties")) {
66
- const lines = bufferToString(content).split("\n").filter(line => !line.startsWith("#"));
67
- for (const line of lines) {
68
- const [key] = line.split("=");
69
- if (key) {
70
- keys.add(key);
71
- }
72
- }
73
- }
74
- });
75
- return [...keys];
76
- }
77
- }
78
- __decorate([
79
- restoreWhatShouldntBeRenamed()
80
- ], RenameFilesCommand.prototype, "rename", null);
81
- /**
82
- * We might rename appVariantIdHierarchy and dependencies, so we restore them after the renaming.
83
- *
84
- * The decorated method may receive either a Map of files (filename → Buffer) or
85
- * a plain JSON object. Each handler is responsible for a single file (via its
86
- * `accept`), operating on its parsed JSON content:
87
- * - Map case: every file a handler accepts is parsed, snapshotted before the
88
- * renaming, then restored and written back after.
89
- * - JSON case: the object is mutated in-place (its reference is preserved) and
90
- * every handler is applied to it.
91
- */
92
- export function restoreWhatShouldntBeRenamed() {
93
- return function (_target, _propertyKey, descriptor) {
94
- const handlers = [new ManifestRenamingHandler()];
95
- const originalValue = descriptor.value;
96
- descriptor.value = function (...args) {
97
- const renaming = args[0];
98
- const files = renaming;
99
- forEachAccepted(files, handlers, (handler, content) => handler.before(bufferToJson(content)));
100
- originalValue.apply(this, args);
101
- forEachAccepted(files, handlers, (handler, content, filename) => {
102
- const json = bufferToJson(content);
103
- handler.after(json);
104
- files.set(filename, jsonToBuffer(json));
105
- });
106
- return files;
107
- };
108
- };
109
- }
110
- ;
111
- /**
112
- * Parses each file that at least one handler accepts, hands the JSON to the
113
- * given callback along with the accepting handlers, and — when `writeBack` is
114
- * provided — serializes the (possibly mutated) JSON back into that map.
115
- */
116
- function forEachAccepted(files, handlers, callback) {
117
- for (const [filename, content] of files) {
118
- for (const handler of handlers) {
119
- if (handler.accept(filename)) {
120
- callback(handler, content, filename);
121
- }
122
- }
10
+ FileRenamer.rename(files, this.references);
123
11
  }
124
12
  }
125
13
  //# sourceMappingURL=renameFilesCommand.js.map
@@ -1,7 +1,7 @@
1
1
  import { ManifestUpdateCommand } from "./command.js";
2
- import { renameJson } from "../../util/renamingUtil.js";
2
+ import { renameJson } from "../../util/renaming/referenceRenaming.js";
3
3
  import { getSAPUI5DependencyIds } from "../../util/manifestUtil.js";
4
- import ManifestRenamingHandler from "../../util/renamingHandlers/manifestRenamingHandler.js";
4
+ import ManifestRenamingHandler from "../../util/renaming/handlers/manifestRenamingHandler.js";
5
5
  /**
6
6
  * Renames app variant references (base app id -> app variant id) inside the
7
7
  * manifest.json object. This is the manifest scoped counterpart of
@@ -13,7 +13,7 @@ export default class PreviewAdapter implements IAdapter {
13
13
  private fetchEndpointsCommand;
14
14
  constructor(configuration: IConfiguration, cfAdapter?: CFAdapter);
15
15
  createSetupCommandChain(appId: string, repository: IRepository): SetupCommandChain;
16
- createAdaptCommandChain(baseApp: BaseApp, appVariant: AppVariant): AdaptCommandChain;
17
- createManifestPreviewCommandChain(baseApp: BaseApp, appVariant: AppVariant): ManifestUpdateCommandChain;
16
+ createAdaptCommandChain(files: ReadonlyMap<string, Buffer>, appVariant: AppVariant): AdaptCommandChain;
17
+ createManifestPreviewCommandChain(baseApp: BaseApp, appVariant: AppVariant, references: Map<string, string>): ManifestUpdateCommandChain;
18
18
  createPostCommandChain(references: Map<string, string>, adaptationProject: AppVariant, ui5BuilderTools: UI5BuilderTools): PostCommandChain;
19
19
  }
@@ -22,11 +22,11 @@ export default class PreviewAdapter {
22
22
  this.fetchEndpointsCommand
23
23
  ]);
24
24
  }
25
- createAdaptCommandChain(baseApp, appVariant) {
26
- return this.cfAdapter.createAdaptCommandChain(baseApp, appVariant);
25
+ createAdaptCommandChain(files, appVariant) {
26
+ return this.cfAdapter.createAdaptCommandChain(files, appVariant);
27
27
  }
28
- createManifestPreviewCommandChain(baseApp, appVariant) {
29
- return this.cfAdapter.createManifestPreviewCommandChain(baseApp, appVariant);
28
+ createManifestPreviewCommandChain(baseApp, appVariant, references) {
29
+ return this.cfAdapter.createManifestPreviewCommandChain(baseApp, appVariant, references);
30
30
  }
31
31
  createPostCommandChain(references, adaptationProject, ui5BuilderTools) {
32
32
  const serviceCredentialsPromise = dependsOn(this.fetchEndpointsCommand);
@@ -1,7 +1,6 @@
1
1
  import DataSourceManager from "./dataSource/dataSourceManager.js";
2
2
  import I18nManager from "../i18nManager.js";
3
3
  import Language from "../model/language.js";
4
- import ServiceRequestor from "./serviceRequestor.js";
5
4
  import { posix as path } from "path";
6
5
  const I18N_DEFAULT_PATH = "i18n/annotations";
7
6
  const I18N_DEFAULT_MODEL_NAME = "@i18n";
@@ -20,10 +19,9 @@ export default class AbapAnnotationManager {
20
19
  const modelName = I18N_DEFAULT_MODEL_NAME; //`i18n_a9n_${normalisedId}`;
21
20
  const i18nPathName = path.join(prefix, I18N_DEFAULT_PATH);
22
21
  const i18nManager = new I18nManager(modelName, appVariantId, languages);
23
- const serviceRequestor = new ServiceRequestor(this.configuration, this.repository);
24
22
  const dataSourceManager = new DataSourceManager();
25
23
  await dataSourceManager.addDataSources(baseAppManifest["sap.app"]?.dataSources);
26
- const annotationFiles = await dataSourceManager.createAnnotationFiles(languages, i18nManager, serviceRequestor);
24
+ const annotationFiles = await dataSourceManager.createAnnotationFiles(languages, i18nManager, this.repository);
27
25
  const i18nFiles = i18nManager.createFiles(i18nPathName);
28
26
  if (i18nManager.hasTranslations()) {
29
27
  this.updateManifestModel(baseAppManifest, modelName, i18nPathName);
@@ -1,7 +1,7 @@
1
1
  import I18nManager from "../../i18nManager.js";
2
2
  import { IAnnotationDownloadParams } from "./dataSourceOData.js";
3
+ import IRepository from "../../repositories/repository.js";
3
4
  import Language from "../../model/language.js";
4
- import ServiceRequestor from "../serviceRequestor.js";
5
5
  import Transformer from "../transformers/transformer.js";
6
6
  export default class DataSource {
7
7
  protected name: string;
@@ -16,19 +16,20 @@ export default class DataSource {
16
16
  * Get the filename under which it should be stored in dist folder
17
17
  */
18
18
  getFilename(): string;
19
- createAnnotationFile(languages: Language[], i18nManager: I18nManager, serviceRequestor: ServiceRequestor): Promise<{
19
+ createAnnotationFile(languages: Language[], i18nManager: I18nManager, repository: IRepository): Promise<{
20
20
  filename: string;
21
21
  xml: string;
22
22
  }>;
23
23
  /**
24
24
  * Download the annotation for all configured languages
25
25
  * @param languages from configuration
26
- * @param serviceRequestor will download the annotation for all languages
26
+ * @param repository will download the annotation for all languages
27
27
  */
28
28
  private getPromisesPerLanguage;
29
29
  /**
30
30
  * Download annotations and process xml string after it
31
31
  */
32
- downloadAnnotation(language: Language, serviceRequestor: ServiceRequestor): Promise<any>;
33
- afterXmlDownload({ xml, language, serviceRequestor, uri }: IAnnotationDownloadParams): Promise<any>;
32
+ downloadAnnotation(language: Language, repository: IRepository): Promise<any>;
33
+ fetchAnnotation(uri: string, language: Language, repository: IRepository): Promise<string>;
34
+ afterXmlDownload({ xml, language, repository, uri }: IAnnotationDownloadParams): Promise<any>;
34
35
  }
@@ -1,9 +1,21 @@
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 XmlUtil from "../../util/xmlUtil.js";
8
+ import { getLogger } from "@ui5/logger";
9
+ import { retryOnError } from "../../util/commonUtil.js";
10
+ const log = getLogger("@ui5/task-adaptation::DataSource");
2
11
  export default class DataSource {
3
12
  name;
4
13
  uri;
5
14
  jsonTransformers = new Array();
6
15
  constructor(name, uri) {
16
+ if (!/^[\w.\-]+$/.test(name)) {
17
+ throw new Error(`Invalid dataSource name '${name}': must contain only letters, digits, underscores, dots, or hyphens`);
18
+ }
7
19
  this.name = name;
8
20
  this.uri = uri;
9
21
  }
@@ -19,8 +31,8 @@ export default class DataSource {
19
31
  getFilename() {
20
32
  return `annotations/annotation_${this.name}.xml`;
21
33
  }
22
- async createAnnotationFile(languages, i18nManager, serviceRequestor) {
23
- const annotationJsons = this.getPromisesPerLanguage(languages, serviceRequestor);
34
+ async createAnnotationFile(languages, i18nManager, repository) {
35
+ const annotationJsons = this.getPromisesPerLanguage(languages, repository);
24
36
  const annotationJson = await i18nManager.populateTranslations(annotationJsons);
25
37
  const xml = XmlUtil.jsonToXml(await annotationJson.json);
26
38
  return {
@@ -31,31 +43,43 @@ export default class DataSource {
31
43
  /**
32
44
  * Download the annotation for all configured languages
33
45
  * @param languages from configuration
34
- * @param serviceRequestor will download the annotation for all languages
46
+ * @param repository will download the annotation for all languages
35
47
  */
36
- getPromisesPerLanguage(languages, serviceRequestor) {
48
+ getPromisesPerLanguage(languages, repository) {
37
49
  const promises = new Map();
38
50
  for (const language of languages) {
39
- promises.set(language, this.downloadAnnotation(language, serviceRequestor));
51
+ promises.set(language, this.downloadAnnotation(language, repository));
40
52
  }
41
53
  return promises;
42
54
  }
43
55
  /**
44
56
  * Download annotations and process xml string after it
45
57
  */
46
- async downloadAnnotation(language, serviceRequestor) {
47
- const languageXmlContent = await serviceRequestor.downloadAnnotation(this.uri, this.name, language);
48
- if (!languageXmlContent) {
49
- throw new Error(`Xml is undefined for '${this.uri}', name '${this.name}' and language '${language.sap}'`);
58
+ async downloadAnnotation(language, repository) {
59
+ const xml = await this.fetchAnnotation(this.uri, language, repository);
60
+ return this.afterXmlDownload({ xml, language, repository, uri: this.uri });
61
+ }
62
+ //@ts-ignore tsx (esbuild) is not yet implemented the new decorators, but
63
+ //old decorators are already subject of compiler error, but it works. So we
64
+ //wait till esbuild implement it correctly.
65
+ async fetchAnnotation(uri, language, repository) {
66
+ const languageUri = `${uri}?sap-language=${language.sap}`;
67
+ log.verbose(`Getting annotation '${this.name}' ${language} by '${languageUri}'`);
68
+ const xml = await repository.downloadAnnotationFile(languageUri);
69
+ if (!xml) {
70
+ throw new Error(`No files were fetched for '${this.name}' by '${languageUri}'`);
50
71
  }
51
- return this.afterXmlDownload({ xml: languageXmlContent, language, serviceRequestor, uri: this.uri });
72
+ return xml;
52
73
  }
53
- async afterXmlDownload({ xml, language, serviceRequestor, uri }) {
74
+ async afterXmlDownload({ xml, language, repository, uri }) {
54
75
  let json = XmlUtil.xmlToJson(xml);
55
76
  for (const transformer of this.jsonTransformers) {
56
- json = await transformer.transform({ xml, json, language, serviceRequestor, uri });
77
+ json = await transformer.transform({ xml, json, language, repository, uri });
57
78
  }
58
79
  return json;
59
80
  }
60
81
  }
82
+ __decorate([
83
+ retryOnError(1)
84
+ ], DataSource.prototype, "fetchAnnotation", null);
61
85
  //# sourceMappingURL=dataSource.js.map
@@ -1,6 +1,6 @@
1
1
  import I18nManager from "../../i18nManager.js";
2
+ import IRepository from "../../repositories/repository.js";
2
3
  import Language from "../../model/language.js";
3
- import ServiceRequestor from "../serviceRequestor.js";
4
4
  export default class DataSourceManager {
5
5
  private dataSources;
6
6
  private shouldDownload;
@@ -9,5 +9,5 @@ export default class DataSourceManager {
9
9
  * @param dataSourcesJson manifest.json/sap.app/dataSources node
10
10
  */
11
11
  addDataSources(dataSourcesJson: any): Promise<void>;
12
- createAnnotationFiles(languages: Language[], i18nManager: I18nManager, serviceRequestor: ServiceRequestor): Promise<Map<string, string>>;
12
+ createAnnotationFiles(languages: Language[], i18nManager: I18nManager, repository: IRepository): Promise<Map<string, string>>;
13
13
  }
@@ -41,10 +41,10 @@ export default class DataSourceManager {
41
41
  dataSource.updateManifest(dataSourcesJson);
42
42
  }
43
43
  }
44
- async createAnnotationFiles(languages, i18nManager, serviceRequestor) {
44
+ async createAnnotationFiles(languages, i18nManager, repository) {
45
45
  const annotationFiles = new Map();
46
46
  for (const dataSource of this.dataSources) {
47
- const { filename, xml } = await dataSource.createAnnotationFile(languages, i18nManager, serviceRequestor);
47
+ const { filename, xml } = await dataSource.createAnnotationFile(languages, i18nManager, repository);
48
48
  annotationFiles.set(filename, xml);
49
49
  }
50
50
  return annotationFiles;
@@ -1,11 +1,11 @@
1
1
  import DataSource from "./dataSource.js";
2
+ import IRepository from "../../repositories/repository.js";
2
3
  import Language from "../../model/language.js";
3
- import ServiceRequestor from "../serviceRequestor.js";
4
4
  export interface IAnnotationDownloadParams {
5
5
  uri: string;
6
6
  xml: string;
7
7
  language: Language;
8
- serviceRequestor: ServiceRequestor;
8
+ repository: IRepository;
9
9
  }
10
10
  export default class DataSourceOData extends DataSource {
11
11
  private dataSourceJson;
@@ -1,11 +1,11 @@
1
1
  import Language from "../../model/language.js";
2
- import ServiceRequestor from "../serviceRequestor.js";
2
+ import IRepository from "../../repositories/repository.js";
3
3
  export interface TransformerInput {
4
4
  uri: string;
5
5
  json: any;
6
6
  xml: string;
7
7
  language: Language;
8
- serviceRequestor: ServiceRequestor;
8
+ repository: IRepository;
9
9
  }
10
10
  export default interface Transformer {
11
11
  transform(input: TransformerInput): any;
@@ -2,7 +2,7 @@ import Transformer, { TransformerInput } from "../transformers/transformer.js";
2
2
  export default class TraverseReferences implements Transformer {
3
3
  private metadataUrl?;
4
4
  constructor(metadataUrl?: string);
5
- transform({ json, language, serviceRequestor, uri: parentUrl }: TransformerInput): Promise<void>;
5
+ transform({ json, language, repository, uri: parentUrl }: TransformerInput): Promise<void>;
6
6
  private shouldIgnoreUrl;
7
7
  private mergeAnnotations;
8
8
  private static isTraversable;
@@ -6,7 +6,7 @@ export default class TraverseReferences {
6
6
  constructor(metadataUrl) {
7
7
  this.metadataUrl = metadataUrl;
8
8
  }
9
- async transform({ json, language, serviceRequestor, uri: parentUrl }) {
9
+ async transform({ json, language, repository, uri: parentUrl }) {
10
10
  const references = MetadataJsonUtil.getReferences(json).filter(TraverseReferences.isTraversable);
11
11
  const promises = [];
12
12
  for (const { includes, uri: relativeUrl } of references) {
@@ -18,7 +18,7 @@ export default class TraverseReferences {
18
18
  }
19
19
  const name = includes[0]?.namespace;
20
20
  const dataSource = new DataSourceODataAnnotation(name, absoluteUrl, {}, this.metadataUrl);
21
- promises.push(dataSource.downloadAnnotation(language, serviceRequestor)
21
+ promises.push(dataSource.downloadAnnotation(language, repository)
22
22
  .then(childAnnotation => ({ name, childAnnotation })));
23
23
  }
24
24
  const childAnnotations = await Promise.all(promises);
@@ -6,19 +6,17 @@ export default class AppVariant {
6
6
  readonly reference: string;
7
7
  readonly layer: any;
8
8
  readonly content: any;
9
- prefix: string;
10
- movedFiles: Map<string, string>;
11
- private renaming;
9
+ readonly prefix: string;
12
10
  static fromWorkspace(workspace: IWorkspace, projectNamespace: string): Promise<AppVariant>;
13
- static fromProject(): Promise<AppVariant>;
14
11
  static fromFiles(files: ReadonlyMap<string, Buffer>): AppVariant;
15
12
  private constructor();
16
13
  getProcessedFiles(): ReadonlyMap<string, Buffer>;
17
14
  /**
18
- * Since we moved files, we need to update paths where they were referenced.
19
- * To do this we use renameMap function along with renaming ids.
15
+ * The files moved under the prefix folder, as original path -> new path.
16
+ * Computed on demand from the (readonly) sources, so there is no stored
17
+ * cross-phase state to go stale between getProcessedFiles and the post step.
20
18
  */
21
- getRenamingForMovedFiles(): Map<string, string>;
19
+ getMovedFiles(): ReadonlyMap<string, string>;
22
20
  getProcessedManifestChanges(): IChange[];
23
21
  private sortByTimeStamp;
24
22
  private validateManifest;
@@ -2,7 +2,7 @@ import { bufferToJson, dotToUnderscore, isManifestChange } from "./util/commonUt
2
2
  import ResourceUtil, { TEXT_EXTENSIONS } from "./util/resourceUtil.js";
3
3
  import { posix as path } from "path";
4
4
  import { moveFile, moveFiles } from "./util/movingHandler/changeFileMoveHandler.js";
5
- import RenameFilesCommand from "./adapters/commands/renameFilesCommand.js";
5
+ import FileRenamer from "./util/renaming/fileRenamer.js";
6
6
  import { validateAppId } from "./util/validator/validator.js";
7
7
  const CHANGES_EXT = ".change";
8
8
  export default class AppVariant {
@@ -12,22 +12,13 @@ export default class AppVariant {
12
12
  reference;
13
13
  layer;
14
14
  content;
15
- prefix = "";
16
- movedFiles = new Map();
17
- renaming = new Map();
15
+ prefix;
18
16
  static async fromWorkspace(workspace, projectNamespace) {
19
17
  const EXTENSIONS_TO_PROCESS = Array.from(TEXT_EXTENSIONS).join(",");
20
18
  const resources = await workspace.byGlob(`/**/*.{${EXTENSIONS_TO_PROCESS}}`);
21
19
  const files = await ResourceUtil.toFileMap(resources, projectNamespace);
22
20
  return new AppVariant(files, resources);
23
21
  }
24
- static async fromProject() {
25
- // previewManifest only merges manifest changes, that is why we
26
- // just need the app variant descriptor and *.change files from the workspace.
27
- const EXTENSIONS_TO_PROCESS = "change,appdescr_variant";
28
- const files = await ResourceUtil.byGlobInProject(`/**/*.{${EXTENSIONS_TO_PROCESS}}`);
29
- return new AppVariant(files);
30
- }
31
22
  static fromFiles(files) {
32
23
  return new AppVariant(files);
33
24
  }
@@ -47,30 +38,25 @@ export default class AppVariant {
47
38
  this.content = content;
48
39
  // Prefix is a subfolder for the app variant to store js, fragments,
49
40
  // annotations and i18n files. It can be anything, but for convenience
50
- // it is an app variant id.
41
+ // it is the app variant id.
51
42
  this.prefix = dotToUnderscore(this.id);
52
43
  }
53
44
  getProcessedFiles() {
54
45
  const { files, renamingPaths } = moveFiles(this.files, this.prefix, this.id);
55
46
  // Directly rename files that with new paths, this ensures no conflict in further renaming
56
47
  // In later remaming it's not possible to find correct prefix of moved files
57
- new RenameFilesCommand(renamingPaths).execute(files);
48
+ FileRenamer.rename(files, renamingPaths);
58
49
  return files;
59
50
  }
60
51
  ;
61
52
  /**
62
- * Since we moved files, we need to update paths where they were referenced.
63
- * To do this we use renameMap function along with renaming ids.
53
+ * The files moved under the prefix folder, as original path -> new path.
54
+ * Computed on demand from the (readonly) sources, so there is no stored
55
+ * cross-phase state to go stale between getProcessedFiles and the post step.
64
56
  */
65
- getRenamingForMovedFiles() {
66
- const renaming = new Map();
67
- const slashToDot = (str) => str.replaceAll("\/", ".");
68
- this.renaming.forEach((newPath, oldPath) => {
69
- renaming.set(slashToDot(oldPath), slashToDot(newPath));
70
- });
71
- return renaming;
57
+ getMovedFiles() {
58
+ return moveFiles(this.files, this.prefix, this.id).movedFiles;
72
59
  }
73
- ;
74
60
  getProcessedManifestChanges() {
75
61
  // Order: manifest changes first, then *.change files sorted by creation ASC
76
62
  const manifestChanges = structuredClone(this.content) ?? [];
package/dist/baseApp.d.ts CHANGED
@@ -26,4 +26,5 @@ export default class BaseApp {
26
26
  private extractI18nPathFromManifest;
27
27
  private VALIDATION_RULES;
28
28
  private validateProperty;
29
+ static getAppVariantHierarchy(files: ReadonlyMap<string, Buffer>): string[];
29
30
  }
package/dist/baseApp.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import { bufferToJson, trimExtension } from "./util/commonUtil.js";
2
+ import { get } from "./util/objectPath.js";
2
3
  import { validateAppId } from "./util/validator/validator.js";
3
4
  const IGNORE_FILES = [
4
5
  "manifest-bundle.zip",
@@ -83,5 +84,14 @@ export default class BaseApp {
83
84
  validationRule(value);
84
85
  }
85
86
  }
87
+ static getAppVariantHierarchy(files) {
88
+ const manifestBuffer = files.get("manifest.json");
89
+ if (!manifestBuffer) {
90
+ throw new Error("Original application should have manifest.json in root folder");
91
+ }
92
+ const manifest = bufferToJson(manifestBuffer);
93
+ const appVariantIdHierarchy = get(manifest, ["sap.ui5", "appVariantIdHierarchy"], []);
94
+ return appVariantIdHierarchy.map(item => item.appVariantId);
95
+ }
86
96
  }
87
97
  //# sourceMappingURL=baseApp.js.map