@ui5/task-adaptation 1.6.5-rc.1 → 1.6.5-rc.3

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 CHANGED
@@ -2,7 +2,16 @@
2
2
  All notable changes to this project will be documented in this file.
3
3
  This project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
4
4
 
5
- A list of unreleased changes can be found [here](https://github.com/SAP/ui5-task-adaptation/compare/v1.6.5-rc.1...HEAD).
5
+ A list of unreleased changes can be found [here](https://github.com/SAP/ui5-task-adaptation/compare/v1.6.5-rc.3...HEAD).
6
+
7
+ <a name="v1.6.5-rc.3"></a>
8
+ ## [v1.6.5-rc.3] - 2026-04-27
9
+ ### Reverts
10
+ - Release 1.6.5-rc.0
11
+
12
+
13
+ <a name="v1.6.5-rc.2"></a>
14
+ ## [v1.6.5-rc.2] - 2026-04-14
6
15
 
7
16
  <a name="v1.6.5-rc.1"></a>
8
17
  ## [v1.6.5-rc.1] - 2026-04-13
@@ -185,6 +194,8 @@ A list of unreleased changes can be found [here](https://github.com/SAP/ui5-task
185
194
  <a name="v1.0.0"></a>
186
195
  ## v1.0.0 - 2020-12-09
187
196
 
197
+ [v1.6.5-rc.3]: https://github.com/SAP/ui5-task-adaptation/compare/v1.6.5-rc.2...v1.6.5-rc.3
198
+ [v1.6.5-rc.2]: https://github.com/SAP/ui5-task-adaptation/compare/v1.6.5-rc.1...v1.6.5-rc.2
188
199
  [v1.6.5-rc.1]: https://github.com/SAP/ui5-task-adaptation/compare/v1.6.4-rc.3...v1.6.5-rc.1
189
200
  [v1.6.4-rc.3]: https://github.com/SAP/ui5-task-adaptation/compare/v1.6.4-rc.2...v1.6.4-rc.3
190
201
  [v1.6.4-rc.2]: https://github.com/SAP/ui5-task-adaptation/compare/v1.6.4-rc.1...v1.6.4-rc.2
package/REUSE.toml CHANGED
@@ -7,4 +7,4 @@ SPDX-PackageDownloadLocation = "https://github.com/SAP/ui5-task-adaptation"
7
7
  path = "**.**"
8
8
  precedence = "aggregate"
9
9
  SPDX-FileCopyrightText = "2009-2025 SAP SE or an SAP affiliate company"
10
- SPDX-License-Identifier = "Apache-2.0"
10
+ SPDX-License-Identifier = "Apache-2.0"
@@ -62,18 +62,21 @@ export default class AppVariant {
62
62
  }
63
63
  ;
64
64
  getProcessedManifestChanges() {
65
- // Order: manifest changes first, then *.change files
65
+ // Order: manifest changes first, then *.change files sorted by creation ASC
66
66
  const manifestChanges = structuredClone(this.content) ?? [];
67
+ const changeFileChanges = [];
67
68
  this.files.forEach((content, filename) => {
68
69
  if (filename.endsWith(CHANGES_EXT)) {
69
70
  const change = JSON.parse(content);
70
71
  if (isManifestChange(filename, content)) {
71
72
  const { newFilename } = moveFile(filename, content, this.prefix, this.id);
72
73
  this.updateRelativePaths(change, newFilename);
73
- manifestChanges.push(change);
74
+ changeFileChanges.push(change);
74
75
  }
75
76
  }
76
77
  });
78
+ changeFileChanges.sort(FilesUtil.sortByTimeStamp);
79
+ manifestChanges.push(...changeFileChanges);
77
80
  if (this.layer) {
78
81
  manifestChanges.forEach(change => change.layer = this.layer ?? change.layer);
79
82
  }
@@ -68,17 +68,18 @@ export function cached() {
68
68
  return function (_target, _propertyKey, descriptor) {
69
69
  const originalValue = descriptor.value;
70
70
  descriptor.value = async function (...args) {
71
- const repoName = args[0];
72
- const cachebusterToken = args[1];
73
- let files = await CacheHolder.read(repoName, cachebusterToken);
74
- CacheHolder.clearOutdatedExcept(repoName);
71
+ const cachedResource = args[0];
72
+ const { appName, cacheBusterToken: cachebusterToken } = cachedResource;
73
+ const token = await cachebusterToken;
74
+ let files = await CacheHolder.read(appName, token);
75
+ CacheHolder.clearOutdatedExcept(appName);
75
76
  if (files.size === 0) {
76
- log.verbose(`No cache for repo '${repoName}' with token '${cachebusterToken}'. Fetching from HTML5 Repository.`);
77
+ log.verbose(`No cache for repo '${appName}' with token '${token}'. Fetching from HTML5 Repository.`);
77
78
  files = await originalValue.apply(this, args);
78
- await CacheHolder.write(repoName, cachebusterToken, files);
79
+ await CacheHolder.write(appName, token, files);
79
80
  }
80
81
  else {
81
- log.verbose(`Using cached files for repo '${repoName}' with token '${cachebusterToken}'.`);
82
+ log.verbose(`Using cached files for repo '${appName}' with token '${token}'.`);
82
83
  }
83
84
  return files;
84
85
  };
@@ -0,0 +1,4 @@
1
+ export default interface ICachedResource {
2
+ appName: string;
3
+ cacheBusterToken: Promise<string>;
4
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=cachedResource.js.map
package/dist/index.js CHANGED
@@ -24,7 +24,7 @@ export default ({ workspace, options, taskUtil }) => {
24
24
  // latest app variant on top. We reverse the list to process original
25
25
  // application first and then app variants in chronological order.
26
26
  const reversedHierarchy = appVariantIdHierarchy.toReversed();
27
- const fetchFilesPromises = reversedHierarchy.map(({ repoName, cachebusterToken }) => repository.fetch(repoName, cachebusterToken));
27
+ const fetchFilesPromises = reversedHierarchy.map(variant => repository.fetch(variant));
28
28
  fetchFilesPromises.push(Promise.resolve(adaptationProject.files));
29
29
  const appVariants = new Array();
30
30
  const adapt = async (baseAppFiles, appVariantFiles) => {
@@ -5,21 +5,49 @@ import AbapRepository from "./repositories/abapRepository.js";
5
5
  import HTML5Repository from "./repositories/html5Repository.js";
6
6
  import LocalRepository from "./repositories/localRepository.js";
7
7
  import AbapAnnotationManager from "./annotations/abapAnnotationManager.js";
8
- import LocalAnnotationManager from "./annotations/localAnnotationManager.js";
9
- import { validateObject } from "./util/commonUtil.js";
10
8
  import CFAnnotationManager from "./annotations/cfAnnotationManager.js";
9
+ import CFValidator from "./util/validator/cfValidator.js";
10
+ import AbapValidator from "./util/validator/abapValidator.js";
11
+ import { isOneOf } from "./util/validator/validator.js";
12
+ import { LANDSCAPE_TYPES } from "./model/configuration.js";
13
+ import { getLogger } from "@ui5/logger";
14
+ import LocalAnnotationManager from "./annotations/localAnnotationManager.js";
15
+ const log = getLogger("@ui5/task-adaptation::LandscapeConfiguration");
11
16
  export function initialize(configuration) {
12
- validateObject(configuration, ["type"], "should be specified in ui5.yaml configuration: 'cf' or 'abap'");
13
- const repository = getRepository(configuration);
14
- const annotationManager = getAnnotationManager(configuration, repository);
17
+ const type = getTypeByConfiguration(configuration);
18
+ const enhancedConfig = { ...configuration, type };
19
+ const repository = getRepository(enhancedConfig);
20
+ const annotationManager = getAnnotationManager(enhancedConfig, repository);
15
21
  return {
16
- adapter: getAdapter(configuration, annotationManager),
22
+ adapter: getAdapter(enhancedConfig, annotationManager),
17
23
  repository,
18
24
  annotationManager
19
25
  };
20
26
  }
27
+ function getTypeByConfiguration(configuration) {
28
+ const validators = [
29
+ new CFValidator(),
30
+ new AbapValidator(),
31
+ ];
32
+ if (isOneOf(LANDSCAPE_TYPES, configuration.type)) {
33
+ return configuration.type;
34
+ }
35
+ else {
36
+ log.warn("Deprecated behavior: type is not specified or invalid. Should be either 'cf' or 'abap'. Trying to detect the type based on provided configuration");
37
+ for (const validator of validators) {
38
+ try {
39
+ validator.validateConfiguration(configuration);
40
+ return validator.type;
41
+ }
42
+ catch (_error) {
43
+ // Continue to the next validator if validation fails
44
+ }
45
+ }
46
+ throw new Error("'type' should be specified in ui5.yaml configuration: 'cf' or 'abap'");
47
+ }
48
+ }
21
49
  function getAdapter(configuration, annotationManager) {
22
- if (isPreview(configuration)) {
50
+ if (isPreview()) {
23
51
  return new PreviewAdapter(configuration);
24
52
  }
25
53
  switch (configuration.type) {
@@ -32,8 +60,8 @@ function getAdapter(configuration, annotationManager) {
32
60
  }
33
61
  }
34
62
  function getRepository(configuration) {
35
- if (isLocal(configuration)) {
36
- return new LocalRepository(configuration);
63
+ if (isLocal()) {
64
+ return new LocalRepository();
37
65
  }
38
66
  switch (configuration.type) {
39
67
  case "abap":
@@ -45,7 +73,7 @@ function getRepository(configuration) {
45
73
  }
46
74
  }
47
75
  function getAnnotationManager(configuration, repository) {
48
- if (isLocal(configuration)) {
76
+ if (isLocal()) {
49
77
  return new LocalAnnotationManager();
50
78
  }
51
79
  switch (configuration.type) {
@@ -57,10 +85,10 @@ function getAnnotationManager(configuration, repository) {
57
85
  throw new Error(`No annotation manager found for the given configuration type '${configuration.type}'`);
58
86
  }
59
87
  }
60
- function isLocal(configuration) {
61
- return process.env.ADP_BUILDER_MODE === "local" || configuration.mode === "local";
88
+ function isLocal() {
89
+ return process.env.ADP_BUILDER_MODE === "local";
62
90
  }
63
- function isPreview(configuration) {
64
- return process.env.ADP_BUILDER_MODE === "preview" || configuration.mode === "preview";
91
+ function isPreview() {
92
+ return process.env.ADP_BUILDER_MODE === "preview";
65
93
  }
66
94
  //# sourceMappingURL=landscapeConfiguration.js.map
@@ -8,16 +8,16 @@ export interface IConfiguration {
8
8
  org?: string;
9
9
  sapCloudService?: string;
10
10
  destination?: string;
11
- type?: "cf" | "abap";
12
- mode?: "preview" | "local" | "default";
11
+ type?: LandscapeType;
13
12
  languages?: any[] | undefined;
14
13
  enableAnnotationCache?: boolean;
15
14
  enableBetaFeatures?: boolean;
16
15
  writeTempFiles?: any;
17
16
  target?: AbapTarget & IAbapTargetMeta;
18
17
  serviceInstanceName?: string;
19
- adpDir?: string;
20
18
  }
19
+ export declare const LANDSCAPE_TYPES: readonly ["cf", "abap"];
20
+ export type LandscapeType = typeof LANDSCAPE_TYPES[number];
21
21
  export interface IAbapTargetMeta {
22
22
  name?: string;
23
23
  ignoreCertErrors?: boolean;
@@ -1,2 +1,2 @@
1
- export {};
1
+ export const LANDSCAPE_TYPES = ["cf", "abap"];
2
2
  //# sourceMappingURL=configuration.js.map
@@ -61,6 +61,7 @@ export interface IChange {
61
61
  layer?: string;
62
62
  content?: IChangeContent;
63
63
  filename: string;
64
+ creation: string;
64
65
  }
65
66
  export interface IChangeText {
66
67
  i18n: string;
@@ -93,8 +93,14 @@ export default class PreviewManager {
93
93
  const promises = new Map();
94
94
  reuseLibs.forEach(lib => {
95
95
  log.info(`Downloading reuse library '${lib.html5AppName}' version '${lib.html5AppVersion}'`);
96
+ const resource = {
97
+ appName: lib.html5AppName,
98
+ appVersion: lib.html5AppVersion,
99
+ appHostId: lib.html5AppHostId,
100
+ cacheBusterToken: Promise.resolve(lib.html5CacheBusterToken)
101
+ };
96
102
  const promise = repository
97
- .fetchReuseLib(lib.html5AppName, lib.html5CacheBusterToken, lib)
103
+ .fetch(resource)
98
104
  .then((libFiles) => PreviewManager.moveLibraryFiles(libFiles, lib.html5AppName, lib.name));
99
105
  promises.set(lib.html5AppName, promise);
100
106
  });
@@ -2,6 +2,6 @@ import type { AbapServiceProvider } from "@sap-ux/axios-extension";
2
2
  import { IConfiguration } from "../model/types.js";
3
3
  export default class AbapProvider {
4
4
  private provider;
5
+ private abapValidator;
5
6
  get({ target, destination }: IConfiguration): Promise<AbapServiceProvider>;
6
- private static validateAndGetAbapTarget;
7
7
  }
@@ -1,14 +1,14 @@
1
1
  import { createAbapServiceProvider } from "@sap-ux/system-access";
2
- import BtpUtils from "@sap-ux/btp-utils";
3
2
  import { getLogger } from "@ui5/logger";
4
- import { validateObject } from "../util/commonUtil.js";
3
+ import AbapValidator from "../util/validator/abapValidator.js";
5
4
  const log = getLogger("@ui5/task-adaptation::AbapProvider");
6
5
  log.debug = (message) => log.verbose(message);
7
6
  export default class AbapProvider {
8
7
  provider = null;
8
+ abapValidator = new AbapValidator();
9
9
  async get({ target, destination }) {
10
10
  if (!this.provider) {
11
- const abapTarget = AbapProvider.validateAndGetAbapTarget(target, destination);
11
+ const abapTarget = this.abapValidator.validateAndGetAbapTarget(target, destination);
12
12
  if (abapTarget) {
13
13
  this.provider = await createAbapServiceProvider(abapTarget, { ignoreCertErrors: abapTarget.ignoreCertErrors }, true, log);
14
14
  }
@@ -18,20 +18,5 @@ export default class AbapProvider {
18
18
  }
19
19
  return this.provider;
20
20
  }
21
- static validateAndGetAbapTarget(target, destination) {
22
- if (target) {
23
- // if target configuration appears, we validate that it should be
24
- // either target/destination for BAS or target/url for IDE we're
25
- // trying to detect is it destination for BAS or url for IDE
26
- const abapTargetProperties = BtpUtils.isAppStudio() ? ["destination"] : ["url"];
27
- validateObject(target, abapTargetProperties, "should be specified in ui5.yaml configuration/target");
28
- return target;
29
- }
30
- else if (destination) {
31
- log.warn("Destination is deprecated, use target/destination configuration instead");
32
- return { destination };
33
- }
34
- throw new Error("Target should be specified in ui5.yaml configuration to connect the ABAP system");
35
- }
36
21
  }
37
22
  //# sourceMappingURL=abapProvider.js.map
@@ -1,15 +1,16 @@
1
- import { IConfiguration, IMetadata, IReuseLibInfo } from "../model/types.js";
1
+ import { IConfiguration, IMetadata } from "../model/types.js";
2
2
  import AbapProvider from "./abapProvider.js";
3
- import { IAppVariantIdHierarchyItem } from "../model/appVariantIdHierarchyItem.js";
4
3
  import IRepository from "./repository.js";
4
+ import ICachedResource from "../cache/cachedResource.js";
5
+ type IAbapResource = ICachedResource;
5
6
  export default class AbapRepository implements IRepository {
6
7
  private configuration;
7
8
  private abapProvider;
8
9
  constructor(configuration: IConfiguration, abapProvider?: AbapProvider);
9
- fetchReuseLib(_libName: string, _cachebusterToken: string, _lib: IReuseLibInfo): Promise<Map<string, string>>;
10
- getAppVariantIdHierarchy(id: string): Promise<IAppVariantIdHierarchyItem[]>;
10
+ getAppVariantIdHierarchy(id: string): Promise<IAbapResource[]>;
11
11
  getAnnotationMetadata(uri: string): Promise<IMetadata>;
12
12
  downloadAnnotationFile(uri: string): Promise<Map<string, any>>;
13
13
  getMetadata(id: string): Promise<IMetadata>;
14
- fetch(repoName: string, _cachebusterToken: string): Promise<Map<string, string>>;
14
+ fetch(resource: IAbapResource): Promise<Map<string, string>>;
15
15
  }
16
+ export {};
@@ -27,9 +27,6 @@ export default class AbapRepository {
27
27
  this.configuration = configuration;
28
28
  this.abapProvider = abapProvider ? abapProvider : new AbapProvider();
29
29
  }
30
- fetchReuseLib(_libName, _cachebusterToken, _lib) {
31
- throw new Error("Preview is not available on SAP S/4HANA On-Premise or Cloud Systems. Please create a ticket on CA-UI5-FL-ADP-BAS component.");
32
- }
33
30
  async getAppVariantIdHierarchy(id) {
34
31
  const provider = await this.abapProvider.get(this.configuration);
35
32
  const lrep = provider.getLayeredRepository();
@@ -37,15 +34,17 @@ export default class AbapRepository {
37
34
  params: { id }
38
35
  });
39
36
  if (response.status === 200) {
40
- return JSON.parse(response.data)?.appVariantIdHierarchy;
37
+ const hierarchy = JSON.parse(response.data)?.appVariantIdHierarchy;
38
+ return hierarchy.map(item => ({
39
+ appName: item.repoName,
40
+ cacheBusterToken: Promise.resolve(item.cachebusterToken)
41
+ }));
41
42
  }
42
43
  else if (this.configuration.appName) {
43
44
  // Fallback to old API on old ABAP backend or CF for backward compatibility
44
- const metadataResponse = await this.getMetadata(id);
45
45
  return [{
46
- repoName: this.configuration.appName,
47
- appVariantId: id,
48
- cachebusterToken: metadataResponse.changedOn
46
+ appName: this.configuration.appName,
47
+ cacheBusterToken: this.getMetadata(id).then(metadata => metadata.changedOn),
49
48
  }];
50
49
  }
51
50
  throw new Error(`App variant id hierarchy for app id '${id}' is not provided`);
@@ -78,8 +77,8 @@ export default class AbapRepository {
78
77
  id
79
78
  };
80
79
  }
81
- async fetch(repoName, _cachebusterToken) {
82
- const encodedRepoName = encodeURIComponent(repoName);
80
+ async fetch(resource) {
81
+ const encodedRepoName = encodeURIComponent(resource.appName);
83
82
  const provider = await this.abapProvider.get(this.configuration);
84
83
  const ui5Repo = provider.getUi5AbapRepository();
85
84
  const response = await ui5Repo.get(`/Repositories('${encodedRepoName}')`, {
@@ -94,7 +93,7 @@ export default class AbapRepository {
94
93
  const buffer = Buffer.from(data.d.ZipArchive, "base64");
95
94
  return unzipZipEntries(buffer);
96
95
  }
97
- throw new Error(`App '${repoName}' doesn't contain files`);
96
+ throw new Error(`App '${resource.appName}' doesn't contain files`);
98
97
  }
99
98
  }
100
99
  __decorate([
@@ -1,12 +1,16 @@
1
- import { IConfiguration, IReuseLibInfo } from "./../model/types.js";
1
+ import { IConfiguration } from "./../model/types.js";
2
2
  import IRepository from "./repository.js";
3
- import { IAppVariantIdHierarchyItem } from "../model/appVariantIdHierarchyItem.js";
3
+ import ICachedResource from "../cache/cachedResource.js";
4
+ export interface IHtml5Resource extends ICachedResource {
5
+ appVersion: string;
6
+ appHostId: string;
7
+ }
4
8
  export default class HTML5Repository implements IRepository {
5
9
  private configuration;
10
+ private validator;
6
11
  constructor(configuration: IConfiguration);
7
- getAppVariantIdHierarchy(appId: string): Promise<IAppVariantIdHierarchyItem[]>;
8
- fetch(_repoName: string, _cachebusterToken: string): Promise<Map<string, string>>;
9
- fetchReuseLib(_libName: string, _cachebusterToken: string, lib: IReuseLibInfo): Promise<Map<string, string>>;
12
+ getAppVariantIdHierarchy(_appId: string): Promise<IHtml5Resource[]>;
13
+ fetch(resource: IHtml5Resource): Promise<Map<string, string>>;
10
14
  getMetadata(): Promise<any>;
11
15
  private getHtml5RepoInfo;
12
16
  private getHTML5Credentials;
@@ -9,39 +9,30 @@ import RequestUtil from "../util/requestUtil.js";
9
9
  import { getLogger } from "@ui5/logger";
10
10
  import { unzipZipEntries } from "../util/zipUtil.js";
11
11
  import { cached } from "../cache/cacheHolder.js";
12
- import { validateConfiguration } from "../util/commonUtil.js";
12
+ import CFValidator from "../util/validator/cfValidator.js";
13
13
  const log = getLogger("@ui5/task-adaptation::HTML5Repository");
14
14
  export default class HTML5Repository {
15
15
  configuration;
16
+ validator = new CFValidator();
16
17
  constructor(configuration) {
17
18
  this.configuration = configuration;
18
- validateConfiguration(configuration, ["appHostId", "appName", "appVersion"]);
19
+ this.validator.validateConfiguration(configuration);
19
20
  }
20
- async getAppVariantIdHierarchy(appId) {
21
- const metadata = await this.getMetadata();
21
+ async getAppVariantIdHierarchy(_appId) {
22
+ const { appName, appVersion, appHostId } = this.configuration;
23
+ if (!appName || !appVersion || !appHostId) {
24
+ throw new Error("Missing required configuration properties appName, appVersion or appHostId");
25
+ }
22
26
  return [{
23
- repoName: this.configuration.appName,
24
- appVariantId: appId,
25
- cachebusterToken: metadata.changedOn
27
+ appName,
28
+ cacheBusterToken: this.getMetadata().then(metadata => metadata.changedOn),
29
+ appVersion,
30
+ appHostId,
26
31
  }];
27
32
  }
28
- async fetch(_repoName, _cachebusterToken) {
33
+ async fetch(resource) {
29
34
  const { token, baseUri } = await this.getHtml5RepoInfo();
30
- const appData = {
31
- appName: this.configuration.appName,
32
- appVersion: this.configuration.appVersion,
33
- appHostId: this.configuration.appHostId
34
- };
35
- return this.getAppZipEntries(appData, baseUri, token);
36
- }
37
- async fetchReuseLib(_libName, _cachebusterToken, lib) {
38
- const { token, baseUri } = await this.getHtml5RepoInfo();
39
- const libAppData = {
40
- appName: lib.html5AppName,
41
- appVersion: lib.html5AppVersion,
42
- appHostId: lib.html5AppHostId
43
- };
44
- return this.getAppZipEntries(libAppData, baseUri, token);
35
+ return this.getAppZipEntries(resource, baseUri, token);
45
36
  }
46
37
  async getMetadata() {
47
38
  const { token, baseUri } = await this.getHtml5RepoInfo();
@@ -65,17 +56,17 @@ export default class HTML5Repository {
65
56
  async getHTML5Credentials(spaceGuid) {
66
57
  log.verbose("Getting HTML5 Repo Runtime credentials from space " + spaceGuid);
67
58
  const PLAN_NAME = "app-runtime";
68
- const SERVIСE_INSTANCE_NAME = "html5-apps-repo-runtime";
59
+ const SERVICE_INSTANCE_NAME = "html5-apps-repo-runtime";
69
60
  const getParams = {
70
61
  spaceGuids: [spaceGuid],
71
62
  planNames: [PLAN_NAME],
72
- names: [SERVIСE_INSTANCE_NAME]
63
+ names: [SERVICE_INSTANCE_NAME]
73
64
  };
74
65
  const createParams = {
75
66
  spaceGuid,
76
67
  planName: PLAN_NAME,
77
68
  serviceName: "html5-apps-repo",
78
- serviceInstanceName: SERVIСE_INSTANCE_NAME,
69
+ serviceInstanceName: SERVICE_INSTANCE_NAME,
79
70
  tags: ["html5-apps-repo-rt"]
80
71
  };
81
72
  const serviceKeys = await CFUtil.getServiceInstanceKeys(getParams, createParams);
@@ -106,9 +97,10 @@ export default class HTML5Repository {
106
97
  const metadata = await RequestUtil.get(uri, requestOptions);
107
98
  return metadata.find((item) => item.appHostId === appHostId && item.applicationName === appName && item.applicationVersion === appVersion);
108
99
  }
109
- async getAppZipEntries(app, html5RepoBaseUri, token) {
110
- const uri = `${html5RepoBaseUri}/applications/content/${app.appName}-${app.appVersion}/`;
111
- const zip = await this.download(token, app.appHostId, uri);
100
+ async getAppZipEntries(resource, html5RepoBaseUri, token) {
101
+ const { appName, appVersion, appHostId } = resource;
102
+ const uri = `${html5RepoBaseUri}/applications/content/${appName}-${appVersion}/`;
103
+ const zip = await this.download(token, appHostId, uri);
112
104
  return unzipZipEntries(zip);
113
105
  }
114
106
  async download(token, appHostId, uri) {
@@ -132,7 +124,4 @@ export default class HTML5Repository {
132
124
  __decorate([
133
125
  cached()
134
126
  ], HTML5Repository.prototype, "fetch", null);
135
- __decorate([
136
- cached()
137
- ], HTML5Repository.prototype, "fetchReuseLib", null);
138
127
  //# sourceMappingURL=html5Repository.js.map
@@ -1,16 +1,13 @@
1
- import { IAppVariantIdHierarchyItem } from "../model/appVariantIdHierarchyItem.js";
2
- import { IConfiguration } from "../model/configuration.js";
3
- import { IReuseLibInfo } from "../model/types.js";
4
1
  import IRepository from "./repository.js";
2
+ import ICachedResource from "../cache/cachedResource.js";
3
+ export interface ILocalResource extends ICachedResource {
4
+ absolutePath: string;
5
+ }
5
6
  export default class LocalRepository implements IRepository {
6
- private configuration;
7
- constructor(configuration: IConfiguration);
8
7
  downloadAnnotationFile(_uri: string): Promise<Map<string, string>>;
9
- getAppVariantIdHierarchy(appId: string): Promise<IAppVariantIdHierarchyItem[]>;
10
- fetch(appId: string, cachebusterToken: string): Promise<Map<string, string>>;
11
- fetchReuseLib(libName: string, cachebusterToken: string, _lib: IReuseLibInfo): Promise<Map<string, string>>;
8
+ getAppVariantIdHierarchy(appId: string): Promise<ILocalResource[]>;
9
+ fetch(resource: ILocalResource): Promise<Map<string, string>>;
12
10
  private collectAppVariantIdHierarchyItems;
13
11
  private getExistingManifestPath;
14
- private readFilesInBaseAppDir;
15
12
  private getLocalFilesDirectory;
16
13
  }
@@ -4,10 +4,6 @@ import fs from "node:fs/promises";
4
4
  import FsUtil from "../util/fsUtil.js";
5
5
  const log = getLogger("@ui5/task-adaptation::LocalRepository");
6
6
  export default class LocalRepository {
7
- configuration;
8
- constructor(configuration) {
9
- this.configuration = configuration;
10
- }
11
7
  async downloadAnnotationFile(_uri) {
12
8
  log.verbose("Downloading annotation files is not supported in LocalRepository.");
13
9
  return new Map();
@@ -17,26 +13,24 @@ export default class LocalRepository {
17
13
  await this.collectAppVariantIdHierarchyItems(appId, items);
18
14
  return items;
19
15
  }
20
- fetch(appId, cachebusterToken) {
21
- return this.readFilesInBaseAppDir(appId, cachebusterToken);
22
- }
23
- fetchReuseLib(libName, cachebusterToken, _lib) {
24
- return this.readFilesInBaseAppDir(libName, cachebusterToken);
16
+ fetch(resource) {
17
+ log.verbose(`Fetching base app files from local directory: ${resource.absolutePath}`);
18
+ return FsUtil.readFilesRecursively(resource.absolutePath);
25
19
  }
26
20
  async collectAppVariantIdHierarchyItems(appId, items) {
27
21
  const appDir = this.getLocalFilesDirectory(appId);
28
22
  const filenames = [
29
- ["manifest.json"],
30
- ["manifest.appdescr_variant"],
31
- ["webapp", "manifest.json"],
32
- ["webapp", "manifest.appdescr_variant"],
23
+ { path: ["webapp", "manifest.json"], suffix: "" },
24
+ { path: ["webapp", "manifest.appdescr_variant"], suffix: "" },
25
+ { path: ["manifest.json"], suffix: "-opt-static-abap" },
26
+ { path: ["manifest.appdescr_variant"], suffix: "-opt-static-abap" },
33
27
  ];
34
- const filepaths = filenames.map((filename) => path.join(appDir, ...filename));
28
+ const filepaths = filenames.map((filename) => path.join(appDir + filename.suffix, ...filename.path));
35
29
  const existingManifestPath = await this.getExistingManifestPath(filepaths);
36
30
  items.push({
37
- appVariantId: appId,
38
- repoName: appId,
39
- cachebusterToken: path.dirname(existingManifestPath)
31
+ appName: appId,
32
+ cacheBusterToken: Promise.resolve("local"),
33
+ absolutePath: path.dirname(existingManifestPath),
40
34
  });
41
35
  if (existingManifestPath.endsWith("manifest.appdescr_variant")) {
42
36
  const manifestContent = await fs.readFile(existingManifestPath, "utf-8");
@@ -52,12 +46,8 @@ export default class LocalRepository {
52
46
  }
53
47
  throw new Error(`None of the paths exist: '${filePaths.join("', '")}'.`);
54
48
  }
55
- readFilesInBaseAppDir(_appId, cachebusterToken) {
56
- log.verbose(`Fetching base app files from local directory: ${cachebusterToken}`);
57
- return FsUtil.readFilesRecursively(cachebusterToken);
58
- }
59
49
  getLocalFilesDirectory(appId) {
60
- const adpDirConfigured = process.env.ADP_BUILDER_DIR || this.configuration.adpDir;
50
+ const adpDirConfigured = process.env.ADP_BUILDER_DIR;
61
51
  const adpDir = adpDirConfigured
62
52
  ? path.normalize(adpDirConfigured).replace(/\\/g, "/").replace(/\/+$/, "").split("/")
63
53
  : [".."];
@@ -1,8 +1,6 @@
1
- import { IAppVariantIdHierarchyItem } from "../model/appVariantIdHierarchyItem.js";
2
- import { IReuseLibInfo } from "../model/types.js";
1
+ import ICachedResource from "../cache/cachedResource.js";
3
2
  export default interface IRepository {
4
- getAppVariantIdHierarchy(appId: string): Promise<IAppVariantIdHierarchyItem[]>;
5
- fetch(repoName: string, cachebusterToken: string): Promise<Map<string, string>>;
6
- fetchReuseLib(libName: string, cachebusterToken: string, lib: IReuseLibInfo): Promise<Map<string, string>>;
3
+ getAppVariantIdHierarchy(appId: string): Promise<ICachedResource[]>;
4
+ fetch(resource: ICachedResource): Promise<Map<string, string>>;
7
5
  downloadAnnotationFile(uri: string): Promise<Map<string, string>>;
8
6
  }
@@ -1,5 +1,7 @@
1
+ import { IChange } from "../model/types.js";
1
2
  export default class FilesUtil {
2
3
  static filter(files: ReadonlyMap<string, string>): ReadonlyMap<string, string>;
4
+ static sortByTimeStamp(a: IChange, b: IChange): number;
3
5
  /**
4
6
  * 1p. i18n.properties are not renamed and property keys are ignored during
5
7
  * the renaming across the files.
@@ -23,6 +23,13 @@ export default class FilesUtil {
23
23
  });
24
24
  return result;
25
25
  }
26
+ static sortByTimeStamp(a, b) {
27
+ if (a.creation < b.creation)
28
+ return -1;
29
+ if (a.creation > b.creation)
30
+ return 1;
31
+ return 0;
32
+ }
26
33
  /**
27
34
  * 1p. i18n.properties are not renamed and property keys are ignored during
28
35
  * the renaming across the files.
@@ -0,0 +1,8 @@
1
+ import { AbapTarget } from "@sap-ux/system-access";
2
+ import { IAbapTargetMeta, IConfiguration, LandscapeType } from "../../model/configuration.js";
3
+ import IValidator from "./validator.js";
4
+ export default class AbapValidator implements IValidator {
5
+ type: LandscapeType;
6
+ validateAndGetAbapTarget(target: AbapTarget & IAbapTargetMeta | undefined, destination: string | undefined): AbapTarget & IAbapTargetMeta;
7
+ validateConfiguration({ target, destination }: IConfiguration): void;
8
+ }
@@ -0,0 +1,26 @@
1
+ import { validateObject } from "../commonUtil.js";
2
+ import BtpUtils from "@sap-ux/btp-utils";
3
+ import { getLogger } from "@ui5/logger";
4
+ const log = getLogger("@ui5/task-adaptation::AbapValidator");
5
+ export default class AbapValidator {
6
+ type = "abap";
7
+ validateAndGetAbapTarget(target, destination) {
8
+ if (target) {
9
+ // if target configuration appears, we validate that it should be
10
+ // either target/destination for BAS or target/url for IDE we're
11
+ // trying to detect is it destination for BAS or url for IDE
12
+ const abapTargetProperties = BtpUtils.isAppStudio() ? ["destination"] : ["url"];
13
+ validateObject(target, abapTargetProperties, "should be specified in ui5.yaml configuration/target");
14
+ return target;
15
+ }
16
+ else if (destination) {
17
+ log.warn("Destination is deprecated, use target/destination configuration instead");
18
+ return { destination };
19
+ }
20
+ throw new Error("Target should be specified in ui5.yaml configuration to connect the ABAP system");
21
+ }
22
+ validateConfiguration({ target, destination }) {
23
+ this.validateAndGetAbapTarget(target, destination);
24
+ }
25
+ }
26
+ //# sourceMappingURL=abapValidator.js.map
@@ -0,0 +1,6 @@
1
+ import { IConfiguration, LandscapeType } from "../../model/configuration.js";
2
+ import IValidator from "./validator.js";
3
+ export default class CFValidator implements IValidator {
4
+ type: LandscapeType;
5
+ validateConfiguration(configuration: IConfiguration): void;
6
+ }
@@ -0,0 +1,8 @@
1
+ import { validateConfiguration } from "../commonUtil.js";
2
+ export default class CFValidator {
3
+ type = "cf";
4
+ validateConfiguration(configuration) {
5
+ validateConfiguration(configuration, ["appHostId", "appName", "appVersion"]);
6
+ }
7
+ }
8
+ //# sourceMappingURL=cfValidator.js.map
@@ -0,0 +1,6 @@
1
+ import { IConfiguration, LandscapeType } from "../../model/configuration.js";
2
+ export default interface IValidator {
3
+ type: LandscapeType;
4
+ validateConfiguration(configuration: IConfiguration): void;
5
+ }
6
+ export declare function isOneOf<T extends readonly unknown[]>(values: T, value: unknown): value is T[number];
@@ -0,0 +1,4 @@
1
+ export function isOneOf(values, value) {
2
+ return values.includes(value);
3
+ }
4
+ //# sourceMappingURL=validator.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ui5/task-adaptation",
3
- "version": "1.6.5-rc.1",
3
+ "version": "1.6.5-rc.3",
4
4
  "description": "Custom task for ui5-builder which allows building UI5 Flexibility Adaptation Projects for SAP BTP, Cloud Foundry environment",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -35,8 +35,8 @@
35
35
  "dependencies": {
36
36
  "@sap-ux/axios-extension": "^1.22.9",
37
37
  "@sap-ux/btp-utils": "^1.1.3",
38
- "@sap-ux/store": "^1.1.4",
39
- "@sap-ux/system-access": "^0.6.18",
38
+ "@sap-ux/store": "^1.5.13",
39
+ "@sap-ux/system-access": "^0.7.5",
40
40
  "@sap/cf-tools": "^3.2.2",
41
41
  "@ui5/fs": "^4.0.1",
42
42
  "@ui5/logger": "^4.0.1",
@@ -112,7 +112,8 @@
112
112
  "src/adapters/adapter.ts",
113
113
  "src/adapters/previewAdapter.ts",
114
114
  "src/repositories/repository.ts",
115
- "src/annotations/annotationManager.ts"
115
+ "src/annotations/annotationManager.ts",
116
+ "src/cache/cachedResource.ts"
116
117
  ],
117
118
  "check-coverage": true,
118
119
  "statements": 85,