@ui5/task-adaptation 1.6.3 → 1.6.4-rc.1
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 +38 -3
- package/dist/adapters/abapAdapter.d.ts +2 -4
- package/dist/adapters/abapAdapter.js +2 -4
- package/dist/adapters/commands/downloadAnnotationsCommand.d.ts +2 -4
- package/dist/adapters/commands/downloadAnnotationsCommand.js +2 -6
- package/dist/annotations/abapAnnotationManager.d.ts +17 -0
- package/dist/{annotationManager.js → annotations/abapAnnotationManager.js} +12 -10
- package/dist/annotations/annotationManager.d.ts +3 -0
- package/dist/annotations/annotationManager.js +2 -0
- package/dist/annotations/localAnnotationManager.d.ts +4 -0
- package/dist/annotations/localAnnotationManager.js +7 -0
- package/dist/annotations/serviceRequestor.d.ts +3 -3
- package/dist/annotations/serviceRequestor.js +4 -4
- package/dist/bundle.js +119 -2
- package/dist/index.js +5 -6
- package/dist/landscapeConfiguration.d.ts +9 -0
- package/dist/landscapeConfiguration.js +65 -0
- package/dist/model/configuration.d.ts +2 -0
- package/dist/previewManager.d.ts +2 -2
- package/dist/previewManager.js +7 -7
- package/dist/repositories/{abapRepoManager.d.ts → abapRepository.d.ts} +5 -3
- package/dist/repositories/{abapRepoManager.js → abapRepository.js} +17 -4
- package/dist/repositories/html5Repository.d.ts +18 -0
- package/dist/repositories/{html5RepoManager.js → html5Repository.js} +58 -27
- package/dist/repositories/localRepository.d.ts +16 -0
- package/dist/repositories/localRepository.js +62 -0
- package/dist/repositories/repository.d.ts +8 -0
- package/dist/repositories/repository.js +2 -0
- package/dist/util/commonUtil.d.ts +1 -0
- package/dist/util/commonUtil.js +3 -0
- package/dist/util/fsUtil.d.ts +2 -0
- package/dist/util/fsUtil.js +34 -0
- package/package.json +5 -2
- package/scripts/publish.ts +256 -0
- package/scripts/test-integration-prep.sh +4 -0
- package/dist/annotationManager.d.ts +0 -17
- package/dist/processors/abapProcessor.d.ts +0 -18
- package/dist/processors/abapProcessor.js +0 -43
- package/dist/processors/cfProcessor.d.ts +0 -14
- package/dist/processors/cfProcessor.js +0 -46
- package/dist/processors/previewProcessor.d.ts +0 -8
- package/dist/processors/previewProcessor.js +0 -11
- package/dist/processors/processor.d.ts +0 -10
- package/dist/processors/processor.js +0 -39
- package/dist/repositories/html5RepoManager.d.ts +0 -12
|
@@ -1,13 +1,15 @@
|
|
|
1
|
-
import { IConfiguration, IMetadata } from "../model/types.js";
|
|
1
|
+
import { IConfiguration, IMetadata, IReuseLibInfo } from "../model/types.js";
|
|
2
2
|
import AbapProvider from "./abapProvider.js";
|
|
3
3
|
import { IAppVariantIdHierarchyItem } from "../model/appVariantIdHierarchyItem.js";
|
|
4
|
-
|
|
4
|
+
import IRepository from "./repository.js";
|
|
5
|
+
export default class AbapRepository implements IRepository {
|
|
5
6
|
private configuration;
|
|
6
7
|
private abapProvider;
|
|
7
8
|
constructor(configuration: IConfiguration, abapProvider?: AbapProvider);
|
|
9
|
+
fetchReuseLib(_libName: string, _cachebusterToken: string, _lib: IReuseLibInfo): Promise<Map<string, string>>;
|
|
8
10
|
getAppVariantIdHierarchy(id: string): Promise<IAppVariantIdHierarchyItem[]>;
|
|
9
11
|
getAnnotationMetadata(uri: string): Promise<IMetadata>;
|
|
10
12
|
downloadAnnotationFile(uri: string): Promise<Map<string, any>>;
|
|
11
13
|
getMetadata(id: string): Promise<IMetadata>;
|
|
12
|
-
fetch(repoName: string): Promise<Map<string, string>>;
|
|
14
|
+
fetch(repoName: string, _cachebusterToken: string): Promise<Map<string, string>>;
|
|
13
15
|
}
|
|
@@ -1,7 +1,14 @@
|
|
|
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 AbapProvider from "./abapProvider.js";
|
|
2
8
|
import { getLogger } from "@ui5/logger";
|
|
3
9
|
import { unzipZipEntries } from "../util/zipUtil.js";
|
|
4
|
-
|
|
10
|
+
import { cached } from "../cache/cacheHolder.js";
|
|
11
|
+
const log = getLogger("@ui5/task-adaptation::AbapRepository");
|
|
5
12
|
const REQUEST_OPTIONS_XML = {
|
|
6
13
|
responseType: "text",
|
|
7
14
|
headers: {
|
|
@@ -13,13 +20,16 @@ const REQUEST_OPTIONS_JSON = {
|
|
|
13
20
|
"Accept": "application/json"
|
|
14
21
|
}
|
|
15
22
|
};
|
|
16
|
-
export default class
|
|
23
|
+
export default class AbapRepository {
|
|
17
24
|
configuration;
|
|
18
25
|
abapProvider;
|
|
19
26
|
constructor(configuration, abapProvider) {
|
|
20
27
|
this.configuration = configuration;
|
|
21
28
|
this.abapProvider = abapProvider ? abapProvider : new AbapProvider();
|
|
22
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
|
+
}
|
|
23
33
|
async getAppVariantIdHierarchy(id) {
|
|
24
34
|
const provider = await this.abapProvider.get(this.configuration);
|
|
25
35
|
const lrep = provider.getLayeredRepository();
|
|
@@ -68,7 +78,7 @@ export default class AbapRepoManager {
|
|
|
68
78
|
id
|
|
69
79
|
};
|
|
70
80
|
}
|
|
71
|
-
async fetch(repoName) {
|
|
81
|
+
async fetch(repoName, _cachebusterToken) {
|
|
72
82
|
const encodedRepoName = encodeURIComponent(repoName);
|
|
73
83
|
const provider = await this.abapProvider.get(this.configuration);
|
|
74
84
|
const ui5Repo = provider.getUi5AbapRepository();
|
|
@@ -87,4 +97,7 @@ export default class AbapRepoManager {
|
|
|
87
97
|
throw new Error(`App '${repoName}' doesn't contain files`);
|
|
88
98
|
}
|
|
89
99
|
}
|
|
90
|
-
|
|
100
|
+
__decorate([
|
|
101
|
+
cached()
|
|
102
|
+
], AbapRepository.prototype, "fetch", null);
|
|
103
|
+
//# sourceMappingURL=abapRepository.js.map
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { IConfiguration, IReuseLibInfo } from "./../model/types.js";
|
|
2
|
+
import IRepository from "./repository.js";
|
|
3
|
+
import { IAppVariantIdHierarchyItem } from "../model/appVariantIdHierarchyItem.js";
|
|
4
|
+
export default class HTML5Repository implements IRepository {
|
|
5
|
+
private configuration;
|
|
6
|
+
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>>;
|
|
10
|
+
getMetadata(): Promise<any>;
|
|
11
|
+
private getHtml5RepoInfo;
|
|
12
|
+
private getHTML5Credentials;
|
|
13
|
+
private getToken;
|
|
14
|
+
private requestMetadata;
|
|
15
|
+
private getAppZipEntries;
|
|
16
|
+
private download;
|
|
17
|
+
downloadAnnotationFile(_uri: string): Promise<Map<string, string>>;
|
|
18
|
+
}
|
|
@@ -1,24 +1,41 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
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 CFUtil from "../util/cfUtil.js";
|
|
8
|
+
import RequestUtil from "../util/requestUtil.js";
|
|
3
9
|
import { getLogger } from "@ui5/logger";
|
|
4
|
-
import { unzipZipEntries } from "
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
10
|
+
import { unzipZipEntries } from "../util/zipUtil.js";
|
|
11
|
+
import { cached } from "../cache/cacheHolder.js";
|
|
12
|
+
import { validateConfiguration } from "../util/commonUtil.js";
|
|
13
|
+
const log = getLogger("@ui5/task-adaptation::HTML5Repository");
|
|
14
|
+
export default class HTML5Repository {
|
|
15
|
+
configuration;
|
|
16
|
+
constructor(configuration) {
|
|
17
|
+
this.configuration = configuration;
|
|
18
|
+
validateConfiguration(configuration, ["appHostId", "appName", "appVersion"]);
|
|
19
|
+
}
|
|
20
|
+
async getAppVariantIdHierarchy(appId) {
|
|
21
|
+
const metadata = await this.getMetadata();
|
|
22
|
+
return [{
|
|
23
|
+
repoName: this.configuration.appName,
|
|
24
|
+
appVariantId: appId,
|
|
25
|
+
cachebusterToken: metadata.changedOn
|
|
26
|
+
}];
|
|
15
27
|
}
|
|
16
|
-
|
|
17
|
-
const { token, baseUri } = await this.getHtml5RepoInfo(
|
|
18
|
-
|
|
28
|
+
async fetch(_repoName, _cachebusterToken) {
|
|
29
|
+
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);
|
|
19
36
|
}
|
|
20
|
-
|
|
21
|
-
const { token, baseUri } = await this.getHtml5RepoInfo(
|
|
37
|
+
async fetchReuseLib(_libName, _cachebusterToken, lib) {
|
|
38
|
+
const { token, baseUri } = await this.getHtml5RepoInfo();
|
|
22
39
|
const libAppData = {
|
|
23
40
|
appName: lib.html5AppName,
|
|
24
41
|
appVersion: lib.html5AppVersion,
|
|
@@ -26,8 +43,12 @@ export default class HTML5RepoManager {
|
|
|
26
43
|
};
|
|
27
44
|
return this.getAppZipEntries(libAppData, baseUri, token);
|
|
28
45
|
}
|
|
29
|
-
|
|
30
|
-
const
|
|
46
|
+
async getMetadata() {
|
|
47
|
+
const { token, baseUri } = await this.getHtml5RepoInfo();
|
|
48
|
+
return this.requestMetadata(baseUri, token);
|
|
49
|
+
}
|
|
50
|
+
async getHtml5RepoInfo() {
|
|
51
|
+
const spaceGuid = await CFUtil.getSpaceGuid(this.configuration?.space);
|
|
31
52
|
const credentials = await this.getHTML5Credentials(spaceGuid);
|
|
32
53
|
const token = await this.getToken(credentials);
|
|
33
54
|
if (!token || token.length === 0) {
|
|
@@ -41,7 +62,7 @@ export default class HTML5RepoManager {
|
|
|
41
62
|
baseUri: credentials.uri
|
|
42
63
|
};
|
|
43
64
|
}
|
|
44
|
-
|
|
65
|
+
async getHTML5Credentials(spaceGuid) {
|
|
45
66
|
log.verbose("Getting HTML5 Repo Runtime credentials from space " + spaceGuid);
|
|
46
67
|
const PLAN_NAME = "app-runtime";
|
|
47
68
|
const SERVIСE_INSTANCE_NAME = "html5-apps-repo-runtime";
|
|
@@ -60,7 +81,7 @@ export default class HTML5RepoManager {
|
|
|
60
81
|
const serviceKeys = await CFUtil.getServiceInstanceKeys(getParams, createParams);
|
|
61
82
|
return serviceKeys.credentials;
|
|
62
83
|
}
|
|
63
|
-
|
|
84
|
+
async getToken({ uaa }) {
|
|
64
85
|
log.verbose("Getting HTML5 Repo token");
|
|
65
86
|
const auth = Buffer.from(uaa.clientid + ":" + uaa.clientsecret);
|
|
66
87
|
const options = {
|
|
@@ -72,8 +93,8 @@ export default class HTML5RepoManager {
|
|
|
72
93
|
const uri = `${uaa.url}/oauth/token?grant_type=client_credentials`;
|
|
73
94
|
return RequestUtil.get(uri, options).then((json) => json["access_token"]);
|
|
74
95
|
}
|
|
75
|
-
|
|
76
|
-
const { appHostId, appName, appVersion } =
|
|
96
|
+
async requestMetadata(html5RepoBaseUri, token) {
|
|
97
|
+
const { appHostId, appName, appVersion } = this.configuration;
|
|
77
98
|
const uri = `${html5RepoBaseUri}/applications/metadata/`;
|
|
78
99
|
const requestOptions = {
|
|
79
100
|
headers: {
|
|
@@ -85,12 +106,12 @@ export default class HTML5RepoManager {
|
|
|
85
106
|
const metadata = await RequestUtil.get(uri, requestOptions);
|
|
86
107
|
return metadata.find((item) => item.appHostId === appHostId && item.applicationName === appName && item.applicationVersion === appVersion);
|
|
87
108
|
}
|
|
88
|
-
|
|
109
|
+
async getAppZipEntries(app, html5RepoBaseUri, token) {
|
|
89
110
|
const uri = `${html5RepoBaseUri}/applications/content/${app.appName}-${app.appVersion}/`;
|
|
90
111
|
const zip = await this.download(token, app.appHostId, uri);
|
|
91
112
|
return unzipZipEntries(zip);
|
|
92
113
|
}
|
|
93
|
-
|
|
114
|
+
async download(token, appHostId, uri) {
|
|
94
115
|
if (!token) {
|
|
95
116
|
throw new Error("HTML5 token is undefined");
|
|
96
117
|
}
|
|
@@ -103,5 +124,15 @@ export default class HTML5RepoManager {
|
|
|
103
124
|
}
|
|
104
125
|
});
|
|
105
126
|
}
|
|
127
|
+
downloadAnnotationFile(_uri) {
|
|
128
|
+
log.verbose("No annotation processing in CF");
|
|
129
|
+
return Promise.resolve(new Map());
|
|
130
|
+
}
|
|
106
131
|
}
|
|
107
|
-
|
|
132
|
+
__decorate([
|
|
133
|
+
cached()
|
|
134
|
+
], HTML5Repository.prototype, "fetch", null);
|
|
135
|
+
__decorate([
|
|
136
|
+
cached()
|
|
137
|
+
], HTML5Repository.prototype, "fetchReuseLib", null);
|
|
138
|
+
//# sourceMappingURL=html5Repository.js.map
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { IAppVariantIdHierarchyItem } from "../model/appVariantIdHierarchyItem.js";
|
|
2
|
+
import { IConfiguration } from "../model/configuration.js";
|
|
3
|
+
import { IReuseLibInfo } from "../model/types.js";
|
|
4
|
+
import IRepository from "./repository.js";
|
|
5
|
+
export default class LocalRepository implements IRepository {
|
|
6
|
+
private configuration;
|
|
7
|
+
constructor(configuration: IConfiguration);
|
|
8
|
+
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>>;
|
|
12
|
+
private collectAppVariantIdHierarchyItems;
|
|
13
|
+
private getExistingManifestPath;
|
|
14
|
+
private readFilesInBaseAppDir;
|
|
15
|
+
private getLocalFilesDirectory;
|
|
16
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { getLogger } from "@ui5/logger";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import fs from "node:fs/promises";
|
|
4
|
+
import FsUtil from "../util/fsUtil.js";
|
|
5
|
+
const log = getLogger("@ui5/task-adaptation::LocalRepository");
|
|
6
|
+
export default class LocalRepository {
|
|
7
|
+
configuration;
|
|
8
|
+
constructor(configuration) {
|
|
9
|
+
this.configuration = configuration;
|
|
10
|
+
}
|
|
11
|
+
async downloadAnnotationFile(_uri) {
|
|
12
|
+
log.verbose("Downloading annotation files is not supported in LocalRepository.");
|
|
13
|
+
return new Map();
|
|
14
|
+
}
|
|
15
|
+
async getAppVariantIdHierarchy(appId) {
|
|
16
|
+
const items = [];
|
|
17
|
+
await this.collectAppVariantIdHierarchyItems(appId, items);
|
|
18
|
+
return items;
|
|
19
|
+
}
|
|
20
|
+
fetch(appId, _cachebusterToken) {
|
|
21
|
+
return this.readFilesInBaseAppDir(appId);
|
|
22
|
+
}
|
|
23
|
+
fetchReuseLib(libName, _cachebusterToken, _lib) {
|
|
24
|
+
return this.readFilesInBaseAppDir(libName);
|
|
25
|
+
}
|
|
26
|
+
async collectAppVariantIdHierarchyItems(appId, items) {
|
|
27
|
+
items.push({
|
|
28
|
+
appVariantId: appId,
|
|
29
|
+
repoName: appId,
|
|
30
|
+
cachebusterToken: "local"
|
|
31
|
+
});
|
|
32
|
+
const appDir = this.getLocalFilesDirectory(appId);
|
|
33
|
+
const filenames = ["manifest.json", "manifest.appdescr_variant"];
|
|
34
|
+
const filepaths = filenames.map((filename) => path.join(appDir, filename));
|
|
35
|
+
const existingManifestPath = await this.getExistingManifestPath(filepaths);
|
|
36
|
+
if (existingManifestPath.endsWith("manifest.appdescr_variant")) {
|
|
37
|
+
const manifestContent = await fs.readFile(existingManifestPath, "utf-8");
|
|
38
|
+
const manifest = JSON.parse(manifestContent);
|
|
39
|
+
await this.collectAppVariantIdHierarchyItems(manifest.reference, items);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
async getExistingManifestPath(filePaths) {
|
|
43
|
+
const existenceChecks = await Promise.all(filePaths.map((filePath) => FsUtil.exists(filePath)));
|
|
44
|
+
const existingIndex = existenceChecks.findIndex((exists) => exists);
|
|
45
|
+
if (existingIndex !== -1) {
|
|
46
|
+
return filePaths[existingIndex];
|
|
47
|
+
}
|
|
48
|
+
throw new Error(`None of the paths exist: '${filePaths.join("', '")}'.`);
|
|
49
|
+
}
|
|
50
|
+
readFilesInBaseAppDir(appId) {
|
|
51
|
+
const appDir = this.getLocalFilesDirectory(appId);
|
|
52
|
+
log.verbose(`Fetching base app files from local directory: ${appDir}`);
|
|
53
|
+
return FsUtil.readFilesRecursively(appDir);
|
|
54
|
+
}
|
|
55
|
+
getLocalFilesDirectory(appId) {
|
|
56
|
+
const baseDir = this.configuration.adpDir
|
|
57
|
+
? path.normalize(this.configuration.adpDir).replace(/\\/g, "/").replace(/\/+$/, "").split("/")
|
|
58
|
+
: [".."];
|
|
59
|
+
return path.join(process.cwd(), ...baseDir, appId);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=localRepository.js.map
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { IAppVariantIdHierarchyItem } from "../model/appVariantIdHierarchyItem.js";
|
|
2
|
+
import { IReuseLibInfo } from "../model/types.js";
|
|
3
|
+
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>>;
|
|
7
|
+
downloadAnnotationFile(uri: string): Promise<Map<string, string>>;
|
|
8
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { IConfiguration } from "../model/types.js";
|
|
2
2
|
import Language from "../model/language.js";
|
|
3
3
|
export declare function dotToUnderscore(value: string): string;
|
|
4
|
+
export declare function validateConfiguration<T extends object>(options: T, properties: Array<keyof T>): void;
|
|
4
5
|
export declare function validateObject<T extends object>(options: T, properties: Array<keyof T>, message: string): void;
|
|
5
6
|
export declare function escapeRegex(update: string): string;
|
|
6
7
|
export declare function insertInArray<T>(array: T[], index: number, insert: T): void;
|
package/dist/util/commonUtil.js
CHANGED
|
@@ -9,6 +9,9 @@ const MANIFEST_CHANGE = "appdescr_";
|
|
|
9
9
|
export function dotToUnderscore(value) {
|
|
10
10
|
return value.replace(/\./g, "_");
|
|
11
11
|
}
|
|
12
|
+
export function validateConfiguration(options, properties) {
|
|
13
|
+
validateObject(options, properties, "should be specified in ui5.yaml configuration");
|
|
14
|
+
}
|
|
12
15
|
export function validateObject(options, properties, message) {
|
|
13
16
|
for (const property of properties) {
|
|
14
17
|
if (!options[property]) {
|
package/dist/util/fsUtil.d.ts
CHANGED
package/dist/util/fsUtil.js
CHANGED
|
@@ -36,5 +36,39 @@ export default class FsUtil {
|
|
|
36
36
|
throw e;
|
|
37
37
|
}
|
|
38
38
|
}
|
|
39
|
+
static async readFilesRecursively(rootDirectory) {
|
|
40
|
+
const directoriesToScan = [rootDirectory];
|
|
41
|
+
const fileReadTasks = [];
|
|
42
|
+
while (directoriesToScan.length > 0) {
|
|
43
|
+
const currentDirectory = directoriesToScan.pop();
|
|
44
|
+
if (!currentDirectory) {
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
const entries = await fs.readdir(currentDirectory, { withFileTypes: true });
|
|
48
|
+
for (const entry of entries) {
|
|
49
|
+
const entryPath = path.join(currentDirectory, entry.name);
|
|
50
|
+
if (entry.isDirectory()) {
|
|
51
|
+
directoriesToScan.push(entryPath);
|
|
52
|
+
}
|
|
53
|
+
else if (entry.isFile()) {
|
|
54
|
+
fileReadTasks.push((async () => {
|
|
55
|
+
const relativeFilePath = path.relative(rootDirectory, entryPath);
|
|
56
|
+
const content = await fs.readFile(entryPath, "utf-8");
|
|
57
|
+
return [relativeFilePath, content];
|
|
58
|
+
})());
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return new Map(await Promise.all(fileReadTasks));
|
|
63
|
+
}
|
|
64
|
+
static async exists(filePath) {
|
|
65
|
+
try {
|
|
66
|
+
await fs.access(filePath);
|
|
67
|
+
return true;
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
39
73
|
}
|
|
40
74
|
//# sourceMappingURL=fsUtil.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ui5/task-adaptation",
|
|
3
|
-
"version": "1.6.
|
|
3
|
+
"version": "1.6.4-rc.1",
|
|
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": {
|
|
@@ -115,7 +115,10 @@
|
|
|
115
115
|
"src/model/configuration.ts",
|
|
116
116
|
"src/model/appVariantIdHierarchyItem.ts",
|
|
117
117
|
"src/adapters/adapter.ts",
|
|
118
|
-
"src/adapters/previewAdapter.ts"
|
|
118
|
+
"src/adapters/previewAdapter.ts",
|
|
119
|
+
"src/repositories/repository.ts",
|
|
120
|
+
"src/annotations/annotationManager.ts",
|
|
121
|
+
"src/processors/processor.ts"
|
|
119
122
|
],
|
|
120
123
|
"check-coverage": true,
|
|
121
124
|
"statements": 85,
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
import { promises as fs } from "fs";
|
|
2
|
+
import path from "path";
|
|
3
|
+
import yargs from "yargs";
|
|
4
|
+
import { hideBin } from "yargs/helpers";
|
|
5
|
+
import { Octokit } from "@octokit/rest";
|
|
6
|
+
import { retry } from "@octokit/plugin-retry";
|
|
7
|
+
|
|
8
|
+
const OctokitClass = Octokit.plugin(retry);
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Recursively get all file paths in the workspace root, excluding:
|
|
13
|
+
* - test/lib/integration
|
|
14
|
+
* - test/fixtures
|
|
15
|
+
* - test/expected
|
|
16
|
+
* - test/lib/index.perf.ts
|
|
17
|
+
* Returns relative paths from the root.
|
|
18
|
+
*/
|
|
19
|
+
async function getAllRootFilesExceptTestExclusions(root: string): Promise<string[]> {
|
|
20
|
+
const excludeDirs = [
|
|
21
|
+
"test/lib/integration",
|
|
22
|
+
"test/fixtures",
|
|
23
|
+
"test/expected",
|
|
24
|
+
".git",
|
|
25
|
+
"coverage",
|
|
26
|
+
".DS_Store",
|
|
27
|
+
"node_modules",
|
|
28
|
+
".nyc_output",
|
|
29
|
+
"coverage",
|
|
30
|
+
"dist",
|
|
31
|
+
"dist-debug",
|
|
32
|
+
"dist.zip",
|
|
33
|
+
".env",
|
|
34
|
+
"test/resources/metadata/download"
|
|
35
|
+
];
|
|
36
|
+
const excludeFiles = [
|
|
37
|
+
"test/lib/index.perf.ts",
|
|
38
|
+
"scripts/test-integration-prep.sh",
|
|
39
|
+
"Jenkinsfile"
|
|
40
|
+
];
|
|
41
|
+
|
|
42
|
+
async function walk(dir: string): Promise<string[]> {
|
|
43
|
+
const dirents = await fs.readdir(dir, { withFileTypes: true });
|
|
44
|
+
const files: string[] = [];
|
|
45
|
+
for (const dirent of dirents) {
|
|
46
|
+
const relPath = path.relative(root, path.join(dir, dirent.name));
|
|
47
|
+
if (excludeDirs.some(ex => relPath === ex || relPath.startsWith(ex + path.sep))) {
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
if (excludeFiles.includes(relPath)) {
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
if (dirent.isDirectory()) {
|
|
54
|
+
files.push(...await walk(path.join(dir, dirent.name)));
|
|
55
|
+
} else {
|
|
56
|
+
files.push(relPath);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return files;
|
|
60
|
+
}
|
|
61
|
+
return walk(root);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const FILES = await getAllRootFilesExceptTestExclusions(process.cwd());
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
interface PublishArgs {
|
|
68
|
+
p?: string;
|
|
69
|
+
dryRun?: boolean;
|
|
70
|
+
tag?: string;
|
|
71
|
+
branch?: string;
|
|
72
|
+
[key: string]: unknown;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
async function publish() {
|
|
76
|
+
const argv = yargs(hideBin(process.argv))
|
|
77
|
+
.option("p", {
|
|
78
|
+
type: "string",
|
|
79
|
+
description: "GitHub token (-p)",
|
|
80
|
+
alias: "p"
|
|
81
|
+
})
|
|
82
|
+
.option("dryRun", {
|
|
83
|
+
type: "boolean",
|
|
84
|
+
description: "Run without publishing",
|
|
85
|
+
default: false
|
|
86
|
+
})
|
|
87
|
+
.option("tag", {
|
|
88
|
+
type: "string",
|
|
89
|
+
description: "Publish with a specific tag"
|
|
90
|
+
})
|
|
91
|
+
.option("branch", {
|
|
92
|
+
type: "string",
|
|
93
|
+
description: "Branch to update (default: main)",
|
|
94
|
+
default: "main",
|
|
95
|
+
alias: "b"
|
|
96
|
+
})
|
|
97
|
+
.help()
|
|
98
|
+
.alias("h", "help")
|
|
99
|
+
.parseSync() as PublishArgs;
|
|
100
|
+
|
|
101
|
+
if (argv.dryRun) {
|
|
102
|
+
console.log("Dry run: no publishing will be performed.");
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
const auth = argv.p;
|
|
106
|
+
if (auth) {
|
|
107
|
+
const octokit = new OctokitClass({ auth });
|
|
108
|
+
const ORGANIZATION = "SAP";
|
|
109
|
+
const REPO = "ui5-task-adaptation";
|
|
110
|
+
await uploadToRepo(octokit, ORGANIZATION, REPO, argv.branch);
|
|
111
|
+
if (argv.tag) {
|
|
112
|
+
console.log(`Published with tag: ${argv.tag}`);
|
|
113
|
+
}
|
|
114
|
+
} else {
|
|
115
|
+
console.log("Github token is not provided.");
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
async function getLatestVersion(): Promise<string> {
|
|
121
|
+
const pkg = await fs.readFile(path.join(process.cwd(), "package.json"), { encoding: "utf-8" });
|
|
122
|
+
const pkgJson = JSON.parse(pkg);
|
|
123
|
+
return pkgJson.version;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
async function uploadToRepo(
|
|
128
|
+
octokit: InstanceType<typeof OctokitClass>,
|
|
129
|
+
org: string,
|
|
130
|
+
repo: string,
|
|
131
|
+
branch: string = "main"
|
|
132
|
+
): Promise<void> {
|
|
133
|
+
const fileBlobs = await Promise.all(Object.values(FILES).map(file => toBlob(octokit, org, repo, path.join(process.cwd(), file))));
|
|
134
|
+
const currentCommit = await getCurrentCommit(octokit, org, repo, branch);
|
|
135
|
+
const newTree = await createNewTree(
|
|
136
|
+
octokit,
|
|
137
|
+
org,
|
|
138
|
+
repo,
|
|
139
|
+
fileBlobs,
|
|
140
|
+
FILES,
|
|
141
|
+
currentCommit.treeSha
|
|
142
|
+
);
|
|
143
|
+
const currentVersion = await getLatestVersion();
|
|
144
|
+
const commitMessage = `Release ${currentVersion}`;
|
|
145
|
+
const newCommit = await createNewCommit(
|
|
146
|
+
octokit,
|
|
147
|
+
org,
|
|
148
|
+
repo,
|
|
149
|
+
commitMessage,
|
|
150
|
+
newTree.sha,
|
|
151
|
+
currentCommit.commitSha
|
|
152
|
+
);
|
|
153
|
+
await setBranchToCommit(octokit, org, repo, branch, newCommit.sha);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
async function getCurrentCommit(
|
|
158
|
+
octokit: InstanceType<typeof OctokitClass>,
|
|
159
|
+
org: string,
|
|
160
|
+
repo: string,
|
|
161
|
+
branch: string = "main"
|
|
162
|
+
): Promise<{ commitSha: string; treeSha: string }> {
|
|
163
|
+
const { data: refData } = await octokit.git.getRef({
|
|
164
|
+
owner: org,
|
|
165
|
+
repo,
|
|
166
|
+
ref: `heads/${branch}`,
|
|
167
|
+
});
|
|
168
|
+
const commitSha = refData.object.sha
|
|
169
|
+
const { data: commitData } = await octokit.git.getCommit({
|
|
170
|
+
owner: org,
|
|
171
|
+
repo,
|
|
172
|
+
commit_sha: commitSha,
|
|
173
|
+
});
|
|
174
|
+
return {
|
|
175
|
+
commitSha,
|
|
176
|
+
treeSha: commitData.tree.sha,
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
async function toBlob(
|
|
182
|
+
octokit: InstanceType<typeof OctokitClass>,
|
|
183
|
+
org: string,
|
|
184
|
+
repo: string,
|
|
185
|
+
filePath: string
|
|
186
|
+
): Promise<{ sha: string }> {
|
|
187
|
+
const content = await fs.readFile(filePath, { encoding: "utf8" });
|
|
188
|
+
const blobData = await octokit.git.createBlob({
|
|
189
|
+
owner: org,
|
|
190
|
+
repo,
|
|
191
|
+
content,
|
|
192
|
+
encoding: "utf-8",
|
|
193
|
+
})
|
|
194
|
+
return blobData.data;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
async function createNewTree(
|
|
199
|
+
octokit: InstanceType<typeof OctokitClass>,
|
|
200
|
+
owner: string,
|
|
201
|
+
repo: string,
|
|
202
|
+
blobs: { sha: string }[],
|
|
203
|
+
paths: string[],
|
|
204
|
+
parentTreeSha: string
|
|
205
|
+
): Promise<any> {
|
|
206
|
+
const tree = blobs.map(({ sha }, i) => ({
|
|
207
|
+
path: paths[i],
|
|
208
|
+
mode: "100644" as const,
|
|
209
|
+
type: "blob" as const,
|
|
210
|
+
sha,
|
|
211
|
+
}));
|
|
212
|
+
const { data } = await octokit.git.createTree({
|
|
213
|
+
owner,
|
|
214
|
+
repo,
|
|
215
|
+
tree,
|
|
216
|
+
base_tree: parentTreeSha,
|
|
217
|
+
})
|
|
218
|
+
return data;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
async function createNewCommit(
|
|
223
|
+
octokit: InstanceType<typeof OctokitClass>,
|
|
224
|
+
org: string,
|
|
225
|
+
repo: string,
|
|
226
|
+
message: string,
|
|
227
|
+
currentTreeSha: string,
|
|
228
|
+
currentCommitSha: string
|
|
229
|
+
): Promise<any> {
|
|
230
|
+
const commit = await octokit.git.createCommit({
|
|
231
|
+
owner: org,
|
|
232
|
+
repo,
|
|
233
|
+
message,
|
|
234
|
+
tree: currentTreeSha,
|
|
235
|
+
parents: [currentCommitSha],
|
|
236
|
+
});
|
|
237
|
+
return commit.data;
|
|
238
|
+
};
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
async function setBranchToCommit(
|
|
242
|
+
octokit: InstanceType<typeof OctokitClass>,
|
|
243
|
+
org: string,
|
|
244
|
+
repo: string,
|
|
245
|
+
branch: string = "main",
|
|
246
|
+
commitSha: string
|
|
247
|
+
): Promise<any> {
|
|
248
|
+
return octokit.git.updateRef({
|
|
249
|
+
owner: org,
|
|
250
|
+
repo,
|
|
251
|
+
ref: `heads/${branch}`,
|
|
252
|
+
sha: commitSha,
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
publish();
|