@ui5/task-adaptation 1.6.8 → 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.
- package/.github/workflows/codeql.yml +35 -0
- package/.github/workflows/release-please.yml +53 -0
- package/.release-please-manifest.json +3 -0
- package/CHANGELOG.md +41 -39
- package/dist/adapters/abapAdapter.d.ts +3 -3
- package/dist/adapters/abapAdapter.js +19 -8
- package/dist/adapters/adapter.d.ts +3 -2
- package/dist/adapters/adapter.js +9 -3
- package/dist/adapters/cfAdapter.d.ts +2 -2
- package/dist/adapters/cfAdapter.js +12 -12
- package/dist/adapters/commands/command.js +0 -27
- package/dist/adapters/commands/downloadAnnotationsCommand.d.ts +3 -4
- package/dist/adapters/commands/downloadAnnotationsCommand.js +4 -4
- package/dist/adapters/commands/fetchPreviewResourcesCommand.js +1 -1
- package/dist/adapters/commands/omitDeletedResourcesCommand.d.ts +1 -1
- package/dist/adapters/commands/renameFilesCommand.d.ts +0 -22
- package/dist/adapters/commands/renameFilesCommand.js +2 -114
- package/dist/adapters/commands/renameManifestCommand.js +2 -2
- package/dist/adapters/previewAdapter.d.ts +2 -2
- package/dist/adapters/previewAdapter.js +4 -4
- package/dist/annotations/abapAnnotationManager.js +1 -3
- package/dist/annotations/dataSource/dataSource.d.ts +6 -5
- package/dist/annotations/dataSource/dataSource.js +36 -12
- package/dist/annotations/dataSource/dataSourceManager.d.ts +2 -2
- package/dist/annotations/dataSource/dataSourceManager.js +2 -2
- package/dist/annotations/dataSource/dataSourceOData.d.ts +2 -2
- package/dist/annotations/transformers/transformer.d.ts +2 -2
- package/dist/annotations/transformers/traverseReferences.d.ts +1 -1
- package/dist/annotations/transformers/traverseReferences.js +2 -2
- package/dist/appVariant.d.ts +5 -6
- package/dist/appVariant.js +9 -16
- package/dist/baseApp.d.ts +1 -0
- package/dist/baseApp.js +10 -0
- package/dist/bundle.js +39 -27
- package/dist/cache/cacheHolder.d.ts +6 -12
- package/dist/cache/cacheHolder.js +27 -39
- package/dist/cache/cachedResource.d.ts +2 -1
- package/dist/index.d.ts +5 -6
- package/dist/index.js +47 -40
- package/dist/landscapeConfiguration.d.ts +4 -4
- package/dist/landscapeConfiguration.js +48 -44
- package/dist/model/configuration.d.ts +0 -1
- package/dist/model/types.d.ts +0 -3
- package/dist/repositories/abapRepository.d.ts +1 -1
- package/dist/repositories/abapRepository.js +3 -3
- package/dist/repositories/cacheRepository.d.ts +4 -5
- package/dist/repositories/cacheRepository.js +10 -18
- package/dist/repositories/html5Repository.d.ts +1 -1
- package/dist/repositories/html5Repository.js +2 -2
- package/dist/repositories/localRepository.d.ts +1 -1
- package/dist/repositories/localRepository.js +2 -2
- package/dist/repositories/repository.d.ts +1 -1
- package/dist/util/commonUtil.d.ts +1 -9
- package/dist/util/commonUtil.js +27 -29
- package/dist/util/fsUtil.js +1 -2
- package/dist/util/movingHandler/changeFileMoveHandler.d.ts +1 -0
- package/dist/util/movingHandler/changeFileMoveHandler.js +11 -3
- package/dist/util/referencesBuilder.d.ts +15 -0
- package/dist/util/referencesBuilder.js +35 -0
- package/dist/util/renaming/fileRenamer.d.ts +23 -0
- package/dist/util/renaming/fileRenamer.js +120 -0
- package/dist/util/{renamingHandlers → renaming/handlers}/jsonRenamingHandler.d.ts +0 -2
- package/dist/util/{renamingHandlers → renaming/handlers}/jsonRenamingHandler.js +0 -6
- package/dist/util/{renamingUtil.d.ts → renaming/referenceRenaming.d.ts} +4 -4
- package/dist/util/{renamingUtil.js → renaming/referenceRenaming.js} +8 -8
- package/package.json +4 -3
- package/release-please-config.json +66 -0
- package/dist/annotations/serviceRequestor.d.ts +0 -9
- package/dist/annotations/serviceRequestor.js +0 -62
- /package/dist/util/{renamingHandlers → renaming/handlers}/manifestRenamingHandler.d.ts +0 -0
- /package/dist/util/{renamingHandlers → renaming/handlers}/manifestRenamingHandler.js +0 -0
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import ICachedResource from "../cache/cachedResource.js";
|
|
2
|
-
import { IConfiguration } from "../model/types.js";
|
|
3
2
|
import IRepository from "./repository.js";
|
|
4
3
|
export default class CacheRepository implements IRepository {
|
|
5
|
-
private
|
|
6
|
-
constructor(
|
|
7
|
-
getAppVariantIdHierarchy(
|
|
4
|
+
private repository;
|
|
5
|
+
constructor(repository: IRepository);
|
|
6
|
+
getAppVariantIdHierarchy(appId: string): Promise<ICachedResource[]>;
|
|
8
7
|
fetch(resource: ICachedResource): Promise<Map<string, Buffer>>;
|
|
9
|
-
downloadAnnotationFile(uri: string): Promise<
|
|
8
|
+
downloadAnnotationFile(uri: string): Promise<string>;
|
|
10
9
|
}
|
|
@@ -1,29 +1,21 @@
|
|
|
1
1
|
import CacheHolder from "../cache/cacheHolder.js";
|
|
2
2
|
export default class CacheRepository {
|
|
3
|
-
|
|
4
|
-
constructor(
|
|
5
|
-
this.
|
|
3
|
+
repository;
|
|
4
|
+
constructor(repository) {
|
|
5
|
+
this.repository = repository;
|
|
6
6
|
}
|
|
7
|
-
async getAppVariantIdHierarchy(
|
|
8
|
-
const
|
|
9
|
-
if (
|
|
10
|
-
|
|
7
|
+
async getAppVariantIdHierarchy(appId) {
|
|
8
|
+
const mergedResource = CacheHolder.mergedResource(appId);
|
|
9
|
+
if (await CacheHolder.hasDirectory(mergedResource)) {
|
|
10
|
+
return [mergedResource];
|
|
11
11
|
}
|
|
12
|
-
return
|
|
13
|
-
appName,
|
|
14
|
-
cacheBusterToken: Promise.resolve("")
|
|
15
|
-
}];
|
|
12
|
+
return this.repository.getAppVariantIdHierarchy(appId);
|
|
16
13
|
}
|
|
17
14
|
async fetch(resource) {
|
|
18
|
-
|
|
19
|
-
const cachedFiles = await CacheHolder.readLatest(appName);
|
|
20
|
-
if (cachedFiles.size === 0) {
|
|
21
|
-
throw new Error(`No cached base app found for '${appName}'. Please check the appName or run a full build first to populate the cache.`);
|
|
22
|
-
}
|
|
23
|
-
return cachedFiles;
|
|
15
|
+
return this.repository.fetch(resource);
|
|
24
16
|
}
|
|
25
17
|
downloadAnnotationFile(uri) {
|
|
26
|
-
|
|
18
|
+
return this.repository.downloadAnnotationFile(uri);
|
|
27
19
|
}
|
|
28
20
|
}
|
|
29
21
|
//# sourceMappingURL=cacheRepository.js.map
|
|
@@ -18,5 +18,5 @@ export default class HTML5Repository implements IRepository {
|
|
|
18
18
|
private requestMetadata;
|
|
19
19
|
private getAppZipEntries;
|
|
20
20
|
private download;
|
|
21
|
-
downloadAnnotationFile(_uri: string): Promise<
|
|
21
|
+
downloadAnnotationFile(_uri: string): Promise<string>;
|
|
22
22
|
}
|
|
@@ -25,7 +25,7 @@ export default class HTML5Repository {
|
|
|
25
25
|
}
|
|
26
26
|
return [{
|
|
27
27
|
appName,
|
|
28
|
-
|
|
28
|
+
token: this.getMetadata().then(metadata => metadata.changedOn),
|
|
29
29
|
appVersion,
|
|
30
30
|
appHostId,
|
|
31
31
|
}];
|
|
@@ -118,7 +118,7 @@ export default class HTML5Repository {
|
|
|
118
118
|
}
|
|
119
119
|
downloadAnnotationFile(_uri) {
|
|
120
120
|
log.verbose("No annotation processing in CF");
|
|
121
|
-
return Promise.resolve(
|
|
121
|
+
return Promise.resolve("");
|
|
122
122
|
}
|
|
123
123
|
}
|
|
124
124
|
__decorate([
|
|
@@ -4,7 +4,7 @@ export interface ILocalResource extends ICachedResource {
|
|
|
4
4
|
absolutePath: string;
|
|
5
5
|
}
|
|
6
6
|
export default class LocalRepository implements IRepository {
|
|
7
|
-
downloadAnnotationFile(_uri: string): Promise<
|
|
7
|
+
downloadAnnotationFile(_uri: string): Promise<string>;
|
|
8
8
|
getAppVariantIdHierarchy(appId: string): Promise<ILocalResource[]>;
|
|
9
9
|
fetch(resource: ILocalResource): Promise<Map<string, Buffer>>;
|
|
10
10
|
private buildManifestIndex;
|
|
@@ -7,7 +7,7 @@ const log = getLogger("@ui5/task-adaptation::LocalRepository");
|
|
|
7
7
|
export default class LocalRepository {
|
|
8
8
|
async downloadAnnotationFile(_uri) {
|
|
9
9
|
log.verbose("Downloading annotation files is not supported in LocalRepository.");
|
|
10
|
-
return
|
|
10
|
+
return "";
|
|
11
11
|
}
|
|
12
12
|
async getAppVariantIdHierarchy(appId) {
|
|
13
13
|
const items = [];
|
|
@@ -26,7 +26,7 @@ export default class LocalRepository {
|
|
|
26
26
|
}
|
|
27
27
|
items.push({
|
|
28
28
|
appName: currentAppId,
|
|
29
|
-
|
|
29
|
+
token: Promise.resolve("local"),
|
|
30
30
|
absolutePath: entry.absolutePath,
|
|
31
31
|
});
|
|
32
32
|
if (entry.isVariant) {
|
|
@@ -2,5 +2,5 @@ import ICachedResource from "../cache/cachedResource.js";
|
|
|
2
2
|
export default interface IRepository {
|
|
3
3
|
getAppVariantIdHierarchy(appId: string): Promise<ICachedResource[]>;
|
|
4
4
|
fetch(resource: ICachedResource): Promise<Map<string, Buffer>>;
|
|
5
|
-
downloadAnnotationFile(uri: string): Promise<
|
|
5
|
+
downloadAnnotationFile(uri: string): Promise<string>;
|
|
6
6
|
}
|
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
import Language from "../model/language.js";
|
|
3
|
-
import AppVariant from "../appVariant.js";
|
|
1
|
+
export declare function retryOnError(maxRetries: number): MethodDecorator;
|
|
4
2
|
export declare function dotToUnderscore(value: string): string;
|
|
5
3
|
export declare function bufferToString(buffer: Buffer): string;
|
|
6
4
|
export declare function bufferToJson(buffer: Buffer): any;
|
|
@@ -11,15 +9,9 @@ export declare function validateConfiguration<T extends object>(options: T, prop
|
|
|
11
9
|
export declare function validateObject<T extends object>(options: T, properties: Array<keyof T>, message: string): void;
|
|
12
10
|
export declare function escapeRegex(update: string): string;
|
|
13
11
|
export declare function insertInArray<T>(array: T[], index: number, insert: T): void;
|
|
14
|
-
export declare function writeTempAnnotations({ writeTempFiles }: IConfiguration, name: string, language: Language, content: string): void;
|
|
15
12
|
export declare function trimExtension(filePath: string): string;
|
|
16
13
|
export declare function traverse(json: any, paths: string[], callback: (json: any, key: string | number, paths: string[]) => void): void;
|
|
17
14
|
export declare function logBuilderVersion(): void;
|
|
18
15
|
export declare function logBetaUsage(): void;
|
|
19
16
|
export declare function getUniqueName(existingNames: string[], template: string): string;
|
|
20
17
|
export declare function isManifestChange(filename: string, content: Buffer): boolean;
|
|
21
|
-
/**
|
|
22
|
-
* 4p. Reference map contains searchTerm as key and replacement as value. Base
|
|
23
|
-
* id and app variant ids are renamed to adaptation project id.
|
|
24
|
-
*/
|
|
25
|
-
export declare function getReferences(appVariants: AppVariant[], adaptationProjectId: string): Map<string, string>;
|
package/dist/util/commonUtil.js
CHANGED
|
@@ -2,10 +2,37 @@ import * as Log from "@ui5/logger";
|
|
|
2
2
|
import * as fs from "fs";
|
|
3
3
|
import { fileURLToPath } from "url";
|
|
4
4
|
import { posix as path } from "path";
|
|
5
|
+
import ServerError from "../model/serverError.js";
|
|
5
6
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
6
7
|
const log = Log.getLogger("rollup-plugin-ui5-resolve-task-adaptation");
|
|
7
8
|
const CHANGES_EXT = ".change";
|
|
8
9
|
const MANIFEST_CHANGE = "appdescr_";
|
|
10
|
+
export function retryOnError(maxRetries) {
|
|
11
|
+
return (_target, _propertyKey, descriptor) => {
|
|
12
|
+
const originalMethod = descriptor.value;
|
|
13
|
+
descriptor.value = async function (...args) {
|
|
14
|
+
let retries = 0;
|
|
15
|
+
while (true) {
|
|
16
|
+
try {
|
|
17
|
+
return await originalMethod.apply(this, args);
|
|
18
|
+
}
|
|
19
|
+
catch (error) {
|
|
20
|
+
if (error instanceof ServerError) {
|
|
21
|
+
if (retries === maxRetries) {
|
|
22
|
+
throw new Error(`Error occurred: ${error.message}. Please try again if this is a temporary issue. If not, please create a ticket on CA-UI5-ABA-AIDX`);
|
|
23
|
+
}
|
|
24
|
+
retries++;
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
const message = error?.response?.data ?? error.message;
|
|
28
|
+
throw new Error(`Failed to fetch annotation by '${args[0]}': ${message}`);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
return descriptor;
|
|
34
|
+
};
|
|
35
|
+
}
|
|
9
36
|
export function dotToUnderscore(value) {
|
|
10
37
|
return value.replace(/\./g, "_");
|
|
11
38
|
}
|
|
@@ -40,18 +67,6 @@ export function escapeRegex(update) {
|
|
|
40
67
|
export function insertInArray(array, index, insert) {
|
|
41
68
|
array.splice(index, 0, insert);
|
|
42
69
|
}
|
|
43
|
-
export function writeTempAnnotations({ writeTempFiles }, name, language, content) {
|
|
44
|
-
const TEMP_DIST_FOLDER = path.join(process.cwd(), "dist-debug", name);
|
|
45
|
-
if (writeTempFiles) {
|
|
46
|
-
if (!fs.existsSync(TEMP_DIST_FOLDER)) {
|
|
47
|
-
fs.mkdirSync(TEMP_DIST_FOLDER, { recursive: true });
|
|
48
|
-
}
|
|
49
|
-
if (language) {
|
|
50
|
-
name += "-" + language.i18n;
|
|
51
|
-
}
|
|
52
|
-
fs.writeFileSync(path.join(TEMP_DIST_FOLDER, name + ".xml"), content);
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
70
|
export function trimExtension(filePath) {
|
|
56
71
|
return filePath.replace(/\.[^/.]+$/, "");
|
|
57
72
|
}
|
|
@@ -113,21 +128,4 @@ export function isManifestChange(filename, content) {
|
|
|
113
128
|
}
|
|
114
129
|
return false;
|
|
115
130
|
}
|
|
116
|
-
/**
|
|
117
|
-
* 4p. Reference map contains searchTerm as key and replacement as value. Base
|
|
118
|
-
* id and app variant ids are renamed to adaptation project id.
|
|
119
|
-
*/
|
|
120
|
-
export function getReferences(appVariants, adaptationProjectId) {
|
|
121
|
-
const references = new Map();
|
|
122
|
-
appVariants.forEach((variant, i) => {
|
|
123
|
-
if (i === 0) {
|
|
124
|
-
references.set(variant.reference, adaptationProjectId);
|
|
125
|
-
}
|
|
126
|
-
if (variant.id !== adaptationProjectId) {
|
|
127
|
-
references.set(variant.id, adaptationProjectId);
|
|
128
|
-
}
|
|
129
|
-
variant.getRenamingForMovedFiles().forEach((value, key) => references.set(key, value));
|
|
130
|
-
});
|
|
131
|
-
return references;
|
|
132
|
-
}
|
|
133
131
|
//# sourceMappingURL=commonUtil.js.map
|
package/dist/util/fsUtil.js
CHANGED
|
@@ -41,8 +41,7 @@ export default class FsUtil {
|
|
|
41
41
|
const fileReadTasks = entries
|
|
42
42
|
.filter(entry => entry.isFile())
|
|
43
43
|
.map(async (entry) => {
|
|
44
|
-
const
|
|
45
|
-
const entryPath = path.join(parentPath, entry.name);
|
|
44
|
+
const entryPath = path.join(entry.parentPath, entry.name);
|
|
46
45
|
const relativeFilePath = path.relative(rootDirectory, entryPath).replaceAll("\\", "/");
|
|
47
46
|
const content = await fs.readFile(entryPath);
|
|
48
47
|
return [relativeFilePath, content];
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export declare const moveFiles: (inputFiles: ReadonlyMap<string, Buffer>, prefix: string, id: string) => {
|
|
2
2
|
files: Map<string, Buffer<ArrayBufferLike>>;
|
|
3
3
|
renamingPaths: Map<string, string>;
|
|
4
|
+
movedFiles: Map<string, string>;
|
|
4
5
|
};
|
|
5
6
|
export declare const moveFile: (filename: string, content: Buffer, prefix: string, id: string) => {
|
|
6
7
|
newFilename: string;
|
|
@@ -49,13 +49,21 @@ function getPathWithoutExtensions(filename) {
|
|
|
49
49
|
}
|
|
50
50
|
export const moveFiles = (inputFiles, prefix, id) => {
|
|
51
51
|
const files = new Map();
|
|
52
|
-
|
|
52
|
+
const renamingPaths = new Map();
|
|
53
|
+
// Maps original filename -> new filename for files that were actually
|
|
54
|
+
// moved, so callers can resolve the new location of an omitted resource.
|
|
55
|
+
const movedFiles = new Map();
|
|
53
56
|
inputFiles.forEach((content, filename) => {
|
|
54
57
|
const { newFilename, renamingPath } = moveFile(filename, content, prefix, id);
|
|
55
58
|
files.set(newFilename, content);
|
|
56
|
-
|
|
59
|
+
for (const [from, to] of renamingPath) {
|
|
60
|
+
renamingPaths.set(from, to);
|
|
61
|
+
}
|
|
62
|
+
if (newFilename !== filename) {
|
|
63
|
+
movedFiles.set(filename, newFilename);
|
|
64
|
+
}
|
|
57
65
|
});
|
|
58
|
-
return { files, renamingPaths };
|
|
66
|
+
return { files, renamingPaths, movedFiles };
|
|
59
67
|
};
|
|
60
68
|
export const moveFile = (filename, content, prefix, id) => {
|
|
61
69
|
let newFilename = filename;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fluent builder for the reference map (old id → adaptation project id) used to
|
|
3
|
+
* rename files. Chain `addReferences` and finish with `build`.
|
|
4
|
+
*/
|
|
5
|
+
export default class ReferencesBuilder {
|
|
6
|
+
private readonly references;
|
|
7
|
+
/**
|
|
8
|
+
* Adds the references derived from the app variant id hierarchy stored in
|
|
9
|
+
* the given files' manifest.
|
|
10
|
+
*/
|
|
11
|
+
addReferences(files: ReadonlyMap<string, Buffer>, adaptationProjectId: string): this;
|
|
12
|
+
addReference(from: string, to: string): this;
|
|
13
|
+
build(): Map<string, string>;
|
|
14
|
+
private getReferences;
|
|
15
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import BaseApp from "../baseApp.js";
|
|
2
|
+
/**
|
|
3
|
+
* Fluent builder for the reference map (old id → adaptation project id) used to
|
|
4
|
+
* rename files. Chain `addReferences` and finish with `build`.
|
|
5
|
+
*/
|
|
6
|
+
export default class ReferencesBuilder {
|
|
7
|
+
references = new Map();
|
|
8
|
+
/**
|
|
9
|
+
* Adds the references derived from the app variant id hierarchy stored in
|
|
10
|
+
* the given files' manifest.
|
|
11
|
+
*/
|
|
12
|
+
addReferences(files, adaptationProjectId) {
|
|
13
|
+
const hierarchy = BaseApp.getAppVariantHierarchy(files);
|
|
14
|
+
const references = this.getReferences(hierarchy, adaptationProjectId);
|
|
15
|
+
references.forEach((value, key) => this.references.set(key, value));
|
|
16
|
+
return this;
|
|
17
|
+
}
|
|
18
|
+
addReference(from, to) {
|
|
19
|
+
this.references.set(from, to);
|
|
20
|
+
return this;
|
|
21
|
+
}
|
|
22
|
+
build() {
|
|
23
|
+
return this.references;
|
|
24
|
+
}
|
|
25
|
+
getReferences(appVariantIdHierarchy, adaptationProjectId) {
|
|
26
|
+
const references = new Map();
|
|
27
|
+
for (const appVariantId of appVariantIdHierarchy) {
|
|
28
|
+
if (appVariantId !== adaptationProjectId && !references.has(appVariantId)) {
|
|
29
|
+
references.set(appVariantId, adaptationProjectId);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return references;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=referencesBuilder.js.map
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Renames references (old id → adaptation project id) across all text files in
|
|
3
|
+
* place, leaving i18n .properties files, their keys and SAPUI5 dependency ids
|
|
4
|
+
* untouched.
|
|
5
|
+
*/
|
|
6
|
+
export default class FileRenamer {
|
|
7
|
+
/**
|
|
8
|
+
* 1p. i18n.properties are not renamed and property keys are ignored during
|
|
9
|
+
* the renaming across the files. Stateless: does not use `this`.
|
|
10
|
+
* @param files - all files both base and appVariants
|
|
11
|
+
* @param references - Reference maps of the app variant
|
|
12
|
+
*/
|
|
13
|
+
static rename(files: Map<string, Buffer>, references: Map<string, string>): void;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Snapshots the JSON paths that must survive renaming (e.g.
|
|
17
|
+
* sap.ui5/appVariantIdHierarchy, dependencies), runs the decorated method, then
|
|
18
|
+
* restores them. The decorated method receives a Map of files (filename →
|
|
19
|
+
* Buffer): every file a handler `accept`s is parsed, snapshotted before the
|
|
20
|
+
* renaming and restored + written back after. Each matching file gets its own
|
|
21
|
+
* handler instance so one file's snapshot can't clobber another's.
|
|
22
|
+
*/
|
|
23
|
+
export declare function restoreWhatShouldntBeRenamed(): (_target: any, _propertyKey: string, descriptor: PropertyDescriptor) => void;
|
|
@@ -0,0 +1,120 @@
|
|
|
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 "./handlers/manifestRenamingHandler.js";
|
|
8
|
+
import { stringToBuffer, bufferToString, bufferToJson, jsonToBuffer } from "../commonUtil.js";
|
|
9
|
+
import { getSAPUI5DependencyIds } from "../manifestUtil.js";
|
|
10
|
+
import { renameMap } from "./referenceRenaming.js";
|
|
11
|
+
import { TEXT_EXTENSIONS } from "../resourceUtil.js";
|
|
12
|
+
import { posix as path } from "path";
|
|
13
|
+
function isTextFile(filename) {
|
|
14
|
+
return TEXT_EXTENSIONS.has(path.extname(filename).slice(1));
|
|
15
|
+
}
|
|
16
|
+
function getManifestSAPUI5DependencyIds(files) {
|
|
17
|
+
const manifestFile = files.get("manifest.json");
|
|
18
|
+
return manifestFile ? getSAPUI5DependencyIds(bufferToJson(manifestFile)) : [];
|
|
19
|
+
}
|
|
20
|
+
function getI18nPropertyKeys(files) {
|
|
21
|
+
const keys = new Set();
|
|
22
|
+
files.forEach((content, filename) => {
|
|
23
|
+
if (filename.endsWith(".properties")) {
|
|
24
|
+
const lines = bufferToString(content).split("\n").filter(line => !line.startsWith("#"));
|
|
25
|
+
for (const line of lines) {
|
|
26
|
+
const [key] = line.split("=");
|
|
27
|
+
if (key) {
|
|
28
|
+
keys.add(key);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
return [...keys];
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Renames references (old id → adaptation project id) across all text files in
|
|
37
|
+
* place, leaving i18n .properties files, their keys and SAPUI5 dependency ids
|
|
38
|
+
* untouched.
|
|
39
|
+
*/
|
|
40
|
+
export default class FileRenamer {
|
|
41
|
+
/**
|
|
42
|
+
* 1p. i18n.properties are not renamed and property keys are ignored during
|
|
43
|
+
* the renaming across the files. Stateless: does not use `this`.
|
|
44
|
+
* @param files - all files both base and appVariants
|
|
45
|
+
* @param references - Reference maps of the app variant
|
|
46
|
+
*/
|
|
47
|
+
static rename(files, references) {
|
|
48
|
+
const IGNORE_EXTENSIONS = [".properties"];
|
|
49
|
+
const ignoreInString = [
|
|
50
|
+
...getI18nPropertyKeys(files),
|
|
51
|
+
...getManifestSAPUI5DependencyIds(files)
|
|
52
|
+
];
|
|
53
|
+
const updates = new Map();
|
|
54
|
+
for (const [filename, content] of files) {
|
|
55
|
+
if (!isTextFile(filename)) {
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
if (!IGNORE_EXTENSIONS.some(ext => filename.endsWith(ext))) {
|
|
59
|
+
// 5p. We pass replacements as ignores since we don't want to
|
|
60
|
+
// rename them again. E.g. we replace app.id with
|
|
61
|
+
// customer.app.id, but if we found customer.app.id somewhere,
|
|
62
|
+
// because we applied changes or something, we don't want to
|
|
63
|
+
// rename it again to customer.customer.app.id.
|
|
64
|
+
const renamed = renameMap(bufferToString(content), references, [...references.values(), ...ignoreInString]);
|
|
65
|
+
updates.set(filename, stringToBuffer(renamed));
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
for (const [filename, content] of updates) {
|
|
69
|
+
files.set(filename, content);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
__decorate([
|
|
74
|
+
restoreWhatShouldntBeRenamed()
|
|
75
|
+
], FileRenamer, "rename", null);
|
|
76
|
+
/**
|
|
77
|
+
* Snapshots the JSON paths that must survive renaming (e.g.
|
|
78
|
+
* sap.ui5/appVariantIdHierarchy, dependencies), runs the decorated method, then
|
|
79
|
+
* restores them. The decorated method receives a Map of files (filename →
|
|
80
|
+
* Buffer): every file a handler `accept`s is parsed, snapshotted before the
|
|
81
|
+
* renaming and restored + written back after. Each matching file gets its own
|
|
82
|
+
* handler instance so one file's snapshot can't clobber another's.
|
|
83
|
+
*/
|
|
84
|
+
export function restoreWhatShouldntBeRenamed() {
|
|
85
|
+
return function (_target, _propertyKey, descriptor) {
|
|
86
|
+
const handlerFactories = [() => new ManifestRenamingHandler()];
|
|
87
|
+
const originalValue = descriptor.value;
|
|
88
|
+
descriptor.value = function (...args) {
|
|
89
|
+
const files = args[0];
|
|
90
|
+
// Snapshot the protected paths with a dedicated handler instance per
|
|
91
|
+
// file, so one file's snapshot can't clobber another's. Multiple
|
|
92
|
+
// files can match a handler (e.g. the root manifest.json and a
|
|
93
|
+
// nested cards/.../manifest.json both end with "manifest.json"); a
|
|
94
|
+
// shared handler would let the last-snapshotted file (which may lack
|
|
95
|
+
// appVariantIdHierarchy) wipe the root manifest's value on restore.
|
|
96
|
+
const snapshots = [];
|
|
97
|
+
for (const [filename, content] of files) {
|
|
98
|
+
for (const createHandler of handlerFactories) {
|
|
99
|
+
const handler = createHandler();
|
|
100
|
+
if (handler.accept(filename)) {
|
|
101
|
+
handler.snapshot(bufferToJson(content));
|
|
102
|
+
snapshots.push({ filename, handler });
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
originalValue.apply(this, args);
|
|
107
|
+
for (const { filename, handler } of snapshots) {
|
|
108
|
+
const content = files.get(filename);
|
|
109
|
+
if (content) {
|
|
110
|
+
const json = bufferToJson(content);
|
|
111
|
+
handler.restore(json);
|
|
112
|
+
files.set(filename, jsonToBuffer(json));
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
return files;
|
|
116
|
+
};
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
;
|
|
120
|
+
//# sourceMappingURL=fileRenamer.js.map
|
|
@@ -3,8 +3,6 @@ export default abstract class JsonRenamingHandler {
|
|
|
3
3
|
protected abstract filePath: string;
|
|
4
4
|
protected abstract jsonPathsToRestore: string[];
|
|
5
5
|
accept(filename: string): boolean;
|
|
6
|
-
before(json: any): void;
|
|
7
|
-
after(json: any): void;
|
|
8
6
|
snapshot(json: any): void;
|
|
9
7
|
restore(obj: any): void;
|
|
10
8
|
protected store(obj: any, path: string): void;
|
|
@@ -3,12 +3,6 @@ export default class JsonRenamingHandler {
|
|
|
3
3
|
accept(filename) {
|
|
4
4
|
return filename.endsWith(this.filePath);
|
|
5
5
|
}
|
|
6
|
-
before(json) {
|
|
7
|
-
this.jsonPathsToRestore.forEach(path => this.store(json, path));
|
|
8
|
-
}
|
|
9
|
-
after(json) {
|
|
10
|
-
this.restore(json);
|
|
11
|
-
}
|
|
12
6
|
snapshot(json) {
|
|
13
7
|
this.jsonPathsToRestore.forEach(path => this.store(json, path));
|
|
14
8
|
}
|
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
export declare function rename(content: string, references: string[], replacement: string): string;
|
|
2
2
|
/**
|
|
3
|
-
* A precompiled
|
|
3
|
+
* A precompiled replacer: the regex, replacement lookup and ignore set are built
|
|
4
4
|
* once and can be applied to many strings via `replace` without recompilation.
|
|
5
5
|
*/
|
|
6
|
-
export interface
|
|
6
|
+
export interface CompiledReplacer {
|
|
7
7
|
replace(content: string): string;
|
|
8
8
|
}
|
|
9
9
|
/**
|
|
10
|
-
* Builds a reusable {@link
|
|
10
|
+
* Builds a reusable {@link CompiledReplacer} from the given references and ignore list.
|
|
11
11
|
* The expensive work (regex compilation, lookup construction) happens here once;
|
|
12
12
|
* the returned `replace` is a cheap single pass over each input string. Prefer
|
|
13
13
|
* this over calling {@link renameMap} repeatedly with the same references.
|
|
14
14
|
*
|
|
15
15
|
* Note: mutates `references` by dropping entries whose dot-count doesn't match.
|
|
16
16
|
*/
|
|
17
|
-
export declare function
|
|
17
|
+
export declare function compileReplacer(references: Map<string, string>, ignoreInStrings: string[]): CompiledReplacer;
|
|
18
18
|
export declare function renameMap(content: string, references: Map<string, string>, ignoreInStrings: string[]): string;
|
|
19
19
|
export declare function renameJson(json: Record<string, unknown>, references: Map<string, string>, ignoreInStrings: string[]): void;
|
|
20
20
|
export declare function renameResources(files: ReadonlyMap<string, string>, search: string[], replacement: string): Map<string, string>;
|
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
import { getLogger } from "@ui5/logger";
|
|
2
|
-
const log = getLogger("@ui5/task-adaptation::
|
|
2
|
+
const log = getLogger("@ui5/task-adaptation::ReferenceRenaming");
|
|
3
3
|
const dotToSlash = (string) => string.replaceAll(".", "/");
|
|
4
4
|
const escapeRegex = (string) => string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
5
5
|
export function rename(content, references, replacement) {
|
|
6
6
|
return renameMap(content, new Map(references.map(ref => [ref, replacement])), [replacement]);
|
|
7
7
|
}
|
|
8
8
|
/**
|
|
9
|
-
* Builds a reusable {@link
|
|
9
|
+
* Builds a reusable {@link CompiledReplacer} from the given references and ignore list.
|
|
10
10
|
* The expensive work (regex compilation, lookup construction) happens here once;
|
|
11
11
|
* the returned `replace` is a cheap single pass over each input string. Prefer
|
|
12
12
|
* this over calling {@link renameMap} repeatedly with the same references.
|
|
13
13
|
*
|
|
14
14
|
* Note: mutates `references` by dropping entries whose dot-count doesn't match.
|
|
15
15
|
*/
|
|
16
|
-
export function
|
|
16
|
+
export function compileReplacer(references, ignoreInStrings) {
|
|
17
17
|
const ignoredReferenceKeys = [];
|
|
18
18
|
for (const [key, value] of references) {
|
|
19
19
|
if (value.includes(".") !== key.includes(".")) {
|
|
@@ -96,13 +96,13 @@ export function compileRenamer(references, ignoreInStrings) {
|
|
|
96
96
|
};
|
|
97
97
|
}
|
|
98
98
|
export function renameMap(content, references, ignoreInStrings) {
|
|
99
|
-
return
|
|
99
|
+
return compileReplacer(references, ignoreInStrings).replace(content);
|
|
100
100
|
}
|
|
101
101
|
export function renameJson(json, references, ignoreInStrings) {
|
|
102
|
-
const
|
|
102
|
+
const replacer = compileReplacer(references, ignoreInStrings);
|
|
103
103
|
function processObject(obj) {
|
|
104
104
|
for (const key of Object.keys(obj)) {
|
|
105
|
-
const renamedKey =
|
|
105
|
+
const renamedKey = replacer.replace(key);
|
|
106
106
|
const value = obj[key];
|
|
107
107
|
if (renamedKey !== key) {
|
|
108
108
|
obj[renamedKey] = value;
|
|
@@ -115,7 +115,7 @@ export function renameJson(json, references, ignoreInStrings) {
|
|
|
115
115
|
const target = container;
|
|
116
116
|
const value = target[index];
|
|
117
117
|
if (typeof value === "string") {
|
|
118
|
-
target[index] =
|
|
118
|
+
target[index] = replacer.replace(value);
|
|
119
119
|
}
|
|
120
120
|
else if (Array.isArray(value)) {
|
|
121
121
|
value.forEach((_, i) => processValue(value, i));
|
|
@@ -129,4 +129,4 @@ export function renameJson(json, references, ignoreInStrings) {
|
|
|
129
129
|
export function renameResources(files, search, replacement) {
|
|
130
130
|
return new Map([...files].map(([filepath, content]) => [filepath, rename(content, search, replacement)]));
|
|
131
131
|
}
|
|
132
|
-
//# sourceMappingURL=
|
|
132
|
+
//# sourceMappingURL=referenceRenaming.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ui5/task-adaptation",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.7.0",
|
|
4
4
|
"description": "Custom task for ui5-builder which allows building UI5 Flexibility Adaptation Projects for SAP BTP, Cloud Foundry environment",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"exports": {
|
|
@@ -10,8 +10,9 @@
|
|
|
10
10
|
}
|
|
11
11
|
},
|
|
12
12
|
"scripts": {
|
|
13
|
-
"test": "npm run lint && npm run build && npm run coverage",
|
|
13
|
+
"test": "npm run lint && npm run build && npm run typecheck:test && npm run coverage",
|
|
14
14
|
"lint": "eslint ./src ./test/lib",
|
|
15
|
+
"typecheck:test": "tsc -p ./test/lib/tsconfig.json --noEmit",
|
|
15
16
|
"dev": "mocha --no-timeouts --no-warnings --import=tsx \"test/lib/**/*.spec.ts\"",
|
|
16
17
|
"perf": "mocha --no-timeouts --no-warnings --import=tsx \"test/lib/**/*.perf.ts\"",
|
|
17
18
|
"coverage": "c8 npm run dev",
|
|
@@ -132,4 +133,4 @@
|
|
|
132
133
|
"@rollup/rollup-linux-x64-gnu": "^4.28.1",
|
|
133
134
|
"@rollup/rollup-linux-x64-musl": "^4.28.1"
|
|
134
135
|
}
|
|
135
|
-
}
|
|
136
|
+
}
|