@sap-ux/fe-fpm-writer 0.43.12 → 0.43.13
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/dist/building-block/index.js +1 -1
- package/dist/column/index.js +1 -1
- package/dist/common/file.d.ts +41 -4
- package/dist/common/file.js +28 -16
- package/dist/field/index.js +1 -1
- package/dist/filter/index.js +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +4 -1
- package/dist/page/custom.js +1 -1
- package/dist/section/index.js +2 -2
- package/dist/view/index.js +1 -1
- package/package.json +1 -1
|
@@ -75,7 +75,7 @@ async function generateBuildingBlock(basePath, config, fs) {
|
|
|
75
75
|
// Validate the base and view paths
|
|
76
76
|
fs ??= (0, mem_fs_editor_1.create)((0, mem_fs_1.create)());
|
|
77
77
|
await (0, validate_1.validateBasePath)(basePath, fs, []);
|
|
78
|
-
const fnGenerateId = config.buildingBlockData.generateId ?? (await (0, file_1.createIdGenerator)(basePath, fs));
|
|
78
|
+
const fnGenerateId = config.buildingBlockData.generateId ?? (await (0, file_1.createIdGenerator)({ basePath, fsEditor: fs }));
|
|
79
79
|
if (!fs.exists((0, node_path_1.join)(basePath, viewOrFragmentPath))) {
|
|
80
80
|
throw new Error(`Invalid view path ${viewOrFragmentPath}.`);
|
|
81
81
|
}
|
package/dist/column/index.js
CHANGED
|
@@ -71,7 +71,7 @@ async function generateCustomColumn(basePath, customColumn, fs) {
|
|
|
71
71
|
(0, validate_1.validateVersion)(customColumn.minUI5Version);
|
|
72
72
|
fs ??= (0, mem_fs_editor_1.create)((0, mem_fs_1.create)());
|
|
73
73
|
await (0, validate_1.validateBasePath)(basePath, fs);
|
|
74
|
-
const fnGenerateId = await (0, file_1.createIdGenerator)(basePath, fs);
|
|
74
|
+
const fnGenerateId = await (0, file_1.createIdGenerator)({ basePath, fsEditor: fs });
|
|
75
75
|
const { path: manifestPath, content: manifest } = await (0, utils_1.getManifest)(basePath, fs);
|
|
76
76
|
// merge with defaults
|
|
77
77
|
const completeColumn = enhanceConfig(fs, customColumn, manifestPath, manifest, fnGenerateId);
|
package/dist/common/file.d.ts
CHANGED
|
@@ -1,5 +1,43 @@
|
|
|
1
1
|
import type { CopyOptions, Editor } from 'mem-fs-editor';
|
|
2
2
|
import type { TabInfo } from '../common/types';
|
|
3
|
+
/**
|
|
4
|
+
* Options for creating an ID generator with cached file contents.
|
|
5
|
+
*/
|
|
6
|
+
export interface CreateIdGeneratorWithCacheOptions {
|
|
7
|
+
basePath?: never;
|
|
8
|
+
fsEditor?: never;
|
|
9
|
+
/**
|
|
10
|
+
*
|
|
11
|
+
* cache for file contents to optimize ID generation.
|
|
12
|
+
*/
|
|
13
|
+
fileContentCache: string[];
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Options for creating an ID generator with filesystem access.
|
|
17
|
+
*/
|
|
18
|
+
export interface CreateIdGeneratorWithFilesystemOptions {
|
|
19
|
+
/**
|
|
20
|
+
* Base path of the project.
|
|
21
|
+
*/
|
|
22
|
+
basePath: string;
|
|
23
|
+
/**
|
|
24
|
+
* mem-fs-editor instance.
|
|
25
|
+
*/
|
|
26
|
+
fsEditor: Editor;
|
|
27
|
+
fileContentCache?: string[];
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Options for creating an empty ID generator (no validation).
|
|
31
|
+
*/
|
|
32
|
+
export interface CreateIdGeneratorEmptyOptions {
|
|
33
|
+
basePath?: never;
|
|
34
|
+
fsEditor?: never;
|
|
35
|
+
fileContentCache?: never;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Options for creating an ID generator.
|
|
39
|
+
*/
|
|
40
|
+
export type CreateIdGeneratorOptions = CreateIdGeneratorWithCacheOptions | CreateIdGeneratorWithFilesystemOptions | CreateIdGeneratorEmptyOptions;
|
|
3
41
|
interface ButtonGroup {
|
|
4
42
|
id?: string;
|
|
5
43
|
}
|
|
@@ -65,11 +103,10 @@ export declare function getFragmentAndViewFiles(appPath: string, fs: Editor): Pr
|
|
|
65
103
|
* Creates an ID generator function for a given base path and editor.
|
|
66
104
|
* The generator ensures unique IDs across all fragment and view files in the project.
|
|
67
105
|
*
|
|
68
|
-
* @param
|
|
69
|
-
* @
|
|
70
|
-
* @returns A function that generates unique IDs based on a base ID string
|
|
106
|
+
* @param options - Options for creating the ID generator
|
|
107
|
+
* @returns A function that generates unique IDs based on a base ID string, or a Promise resolving to such function
|
|
71
108
|
*/
|
|
72
|
-
export declare function createIdGenerator(
|
|
109
|
+
export declare function createIdGenerator(options?: CreateIdGeneratorOptions): Promise<IdGeneratorFunction> | IdGeneratorFunction;
|
|
73
110
|
export declare const COPY_TEMPLATE_OPTIONS: CopyOptions & {
|
|
74
111
|
noGlob: boolean;
|
|
75
112
|
};
|
package/dist/common/file.js
CHANGED
|
@@ -10,7 +10,7 @@ exports.copyTpl = copyTpl;
|
|
|
10
10
|
exports.getRelativeTemplateComponentPath = getRelativeTemplateComponentPath;
|
|
11
11
|
const node_path_1 = require("node:path");
|
|
12
12
|
const file_1 = require("@sap-ux/project-access/dist/file");
|
|
13
|
-
const
|
|
13
|
+
const xmldom_1 = require("@xmldom/xmldom");
|
|
14
14
|
const CHAR_SPACE = ' ';
|
|
15
15
|
const CHAR_TAB = '\t';
|
|
16
16
|
exports.CONFIG = {
|
|
@@ -105,20 +105,24 @@ exports.CONFIG = {
|
|
|
105
105
|
* Generates a unique element ID that is not already used in any view or fragment file.
|
|
106
106
|
* Uses an incremental counter for predictable, readable IDs.
|
|
107
107
|
*
|
|
108
|
-
* @param fs - The file system object for reading files
|
|
109
108
|
* @param baseId - The base name for the ID (e.g., 'filterBar', 'chart')
|
|
110
|
-
* @param
|
|
109
|
+
* @param filteredFilesContent - The list of files to check for ID availability
|
|
111
110
|
* @param validatedIds - A list of IDs that have already been validated in the current session to avoid duplicates
|
|
112
111
|
* @returns A unique ID that is available across all view and fragment files
|
|
113
112
|
*/
|
|
114
|
-
function generateUniqueElementId(
|
|
113
|
+
function generateUniqueElementId(baseId, filteredFilesContent, validatedIds = []) {
|
|
115
114
|
const maxAttempts = 1000;
|
|
116
|
-
|
|
115
|
+
function checkElementIdAvailable(id, xmlContent) {
|
|
116
|
+
const xmlDocument = new xmldom_1.DOMParser({ errorHandler: () => { } }).parseFromString(xmlContent);
|
|
117
|
+
return xmlDocument.documentElement ? !xmlDocument.getElementById(id) : true;
|
|
118
|
+
}
|
|
119
|
+
if (filteredFilesContent.every((content) => content === '' || checkElementIdAvailable(baseId, content)) &&
|
|
120
|
+
!validatedIds.includes(baseId)) {
|
|
117
121
|
return baseId;
|
|
118
122
|
}
|
|
119
123
|
for (let counter = 1; counter < maxAttempts; counter++) {
|
|
120
124
|
const candidateId = `${baseId}${counter}`;
|
|
121
|
-
if (
|
|
125
|
+
if (filteredFilesContent.every((content) => content === '' || checkElementIdAvailable(candidateId, content)) &&
|
|
122
126
|
!validatedIds.includes(candidateId)) {
|
|
123
127
|
return candidateId;
|
|
124
128
|
}
|
|
@@ -142,18 +146,26 @@ async function getFragmentAndViewFiles(appPath, fs) {
|
|
|
142
146
|
* Creates an ID generator function for a given base path and editor.
|
|
143
147
|
* The generator ensures unique IDs across all fragment and view files in the project.
|
|
144
148
|
*
|
|
145
|
-
* @param
|
|
146
|
-
* @
|
|
147
|
-
* @returns A function that generates unique IDs based on a base ID string
|
|
149
|
+
* @param options - Options for creating the ID generator
|
|
150
|
+
* @returns A function that generates unique IDs based on a base ID string, or a Promise resolving to such function
|
|
148
151
|
*/
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
return generateUniqueElementId(fsEditor, baseId, files, validatedIds);
|
|
152
|
+
function createIdGenerator(options = {}) {
|
|
153
|
+
const { basePath, fsEditor, fileContentCache = [] } = options;
|
|
154
|
+
const createGenerator = (fileContents) => {
|
|
155
|
+
return (baseId, validatedIds = []) => {
|
|
156
|
+
return generateUniqueElementId(baseId, fileContents, validatedIds);
|
|
157
|
+
};
|
|
156
158
|
};
|
|
159
|
+
if (fileContentCache.length > 0) {
|
|
160
|
+
return createGenerator(fileContentCache);
|
|
161
|
+
}
|
|
162
|
+
if (fsEditor && basePath) {
|
|
163
|
+
return getFragmentAndViewFiles(basePath, fsEditor).then((filePaths) => {
|
|
164
|
+
const fileContents = filePaths.map((path) => fsEditor.read(path).toString());
|
|
165
|
+
return createGenerator(fileContents);
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
return createGenerator([]);
|
|
157
169
|
}
|
|
158
170
|
// `noGlob` is supported in `mem-fs-editor` v9,
|
|
159
171
|
// but is missing from `@types/mem-fs-editor` (no v9 typings), so we extend the type here.
|
package/dist/field/index.js
CHANGED
|
@@ -53,7 +53,7 @@ async function generateCustomField(basePath, customField, fs) {
|
|
|
53
53
|
(0, validate_1.validateVersion)(customField.minUI5Version);
|
|
54
54
|
fs ??= (0, mem_fs_editor_1.create)((0, mem_fs_1.create)());
|
|
55
55
|
await (0, validate_1.validateBasePath)(basePath, fs);
|
|
56
|
-
const generateId = await (0, file_1.createIdGenerator)(basePath, fs);
|
|
56
|
+
const generateId = await (0, file_1.createIdGenerator)({ basePath, fsEditor: fs });
|
|
57
57
|
const { path: manifestPath, content: manifest } = await (0, utils_1.getManifest)(basePath, fs);
|
|
58
58
|
// merge with defaults
|
|
59
59
|
const completeField = enhanceConfig(fs, customField, manifestPath, manifest, generateId);
|
package/dist/filter/index.js
CHANGED
|
@@ -48,7 +48,7 @@ async function generateCustomFilter(basePath, filterConfig, fs) {
|
|
|
48
48
|
fs = (0, mem_fs_editor_1.create)((0, mem_fs_1.create)());
|
|
49
49
|
}
|
|
50
50
|
await (0, validate_1.validateBasePath)(basePath, fs);
|
|
51
|
-
const fnGenerateId = await (0, file_1.createIdGenerator)(basePath, fs);
|
|
51
|
+
const fnGenerateId = await (0, file_1.createIdGenerator)({ basePath, fsEditor: fs });
|
|
52
52
|
const { path: manifestPath, content: manifest } = await (0, utils_1.getManifest)(basePath, fs);
|
|
53
53
|
const config = enhanceConfig(filterConfig, manifestPath, manifest);
|
|
54
54
|
// Apply event handler
|
package/dist/index.d.ts
CHANGED
|
@@ -14,6 +14,7 @@ export { CustomView } from './view/types';
|
|
|
14
14
|
export { generateCustomView } from './view';
|
|
15
15
|
export { enableFPM, FPMConfig } from './app';
|
|
16
16
|
export { validateBasePath, validateVersion } from './common/validate';
|
|
17
|
+
export { createIdGenerator, type IdGeneratorFunction, getRelativeTemplateComponentPath } from './common/file';
|
|
17
18
|
export { BuildingBlockType, FilterBar, Form, Chart, Field, FieldFormatOptions, Table, BuildingBlockConfig, Page, CustomColumn, CustomFilterField, RichTextEditor, ButtonGroupConfig, Action } from './building-block/types';
|
|
18
19
|
export { generateBuildingBlock, getSerializedFileContent } from './building-block';
|
|
19
20
|
export { ChartPromptsAnswer, FilterBarPromptsAnswer, FormPromptsAnswer, TablePromptsAnswer, PagePromptsAnswer, RichTextEditorPromptsAnswer, RichTextEditorButtonGroupsPromptsAnswer, BuildingBlockTypePromptsAnswer } from './building-block/prompts/questions';
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.initI18n = exports.generateCustomField = exports.generateControllerExtension = exports.ControllerExtensionPageType = exports.PromptsAPI = exports.PromptsType = exports.getSerializedFileContent = exports.generateBuildingBlock = exports.BuildingBlockType = exports.validateVersion = exports.validateBasePath = exports.enableFPM = exports.generateCustomView = exports.generateCustomFilter = exports.generateCustomHeaderSection = exports.generateCustomSubSection = exports.generateCustomSection = exports.DesignTime = exports.RequestGroupId = exports.generateCustomColumn = exports.generateActionMenu = exports.ActionMenuTargetControl = exports.generateCustomAction = exports.TargetControl = exports.generateListReport = exports.generateObjectPage = exports.generateCustomPage = void 0;
|
|
3
|
+
exports.initI18n = exports.generateCustomField = exports.generateControllerExtension = exports.ControllerExtensionPageType = exports.PromptsAPI = exports.PromptsType = exports.getSerializedFileContent = exports.generateBuildingBlock = exports.BuildingBlockType = exports.getRelativeTemplateComponentPath = exports.createIdGenerator = exports.validateVersion = exports.validateBasePath = exports.enableFPM = exports.generateCustomView = exports.generateCustomFilter = exports.generateCustomHeaderSection = exports.generateCustomSubSection = exports.generateCustomSection = exports.DesignTime = exports.RequestGroupId = exports.generateCustomColumn = exports.generateActionMenu = exports.ActionMenuTargetControl = exports.generateCustomAction = exports.TargetControl = exports.generateListReport = exports.generateObjectPage = exports.generateCustomPage = void 0;
|
|
4
4
|
var page_1 = require("./page");
|
|
5
5
|
Object.defineProperty(exports, "generateCustomPage", { enumerable: true, get: function () { return page_1.generateCustomPage; } });
|
|
6
6
|
Object.defineProperty(exports, "generateObjectPage", { enumerable: true, get: function () { return page_1.generateObjectPage; } });
|
|
@@ -31,6 +31,9 @@ Object.defineProperty(exports, "enableFPM", { enumerable: true, get: function ()
|
|
|
31
31
|
var validate_1 = require("./common/validate");
|
|
32
32
|
Object.defineProperty(exports, "validateBasePath", { enumerable: true, get: function () { return validate_1.validateBasePath; } });
|
|
33
33
|
Object.defineProperty(exports, "validateVersion", { enumerable: true, get: function () { return validate_1.validateVersion; } });
|
|
34
|
+
var file_1 = require("./common/file");
|
|
35
|
+
Object.defineProperty(exports, "createIdGenerator", { enumerable: true, get: function () { return file_1.createIdGenerator; } });
|
|
36
|
+
Object.defineProperty(exports, "getRelativeTemplateComponentPath", { enumerable: true, get: function () { return file_1.getRelativeTemplateComponentPath; } });
|
|
34
37
|
var types_4 = require("./building-block/types");
|
|
35
38
|
Object.defineProperty(exports, "BuildingBlockType", { enumerable: true, get: function () { return types_4.BuildingBlockType; } });
|
|
36
39
|
var building_block_1 = require("./building-block");
|
package/dist/page/custom.js
CHANGED
|
@@ -118,7 +118,7 @@ async function generate(basePath, data, fs, log) {
|
|
|
118
118
|
(0, validate_1.validateVersion)(data.minUI5Version);
|
|
119
119
|
await (0, common_1.validatePageConfig)(basePath, data, fs, []);
|
|
120
120
|
const manifestPath = await (0, utils_1.getManifestPath)(basePath, fs);
|
|
121
|
-
const fnGenerateId = await (0, file_1.createIdGenerator)(basePath, fs);
|
|
121
|
+
const fnGenerateId = await (0, file_1.createIdGenerator)({ basePath, fsEditor: fs });
|
|
122
122
|
const config = enhanceData(data, manifestPath, fs);
|
|
123
123
|
// merge content into existing files
|
|
124
124
|
const root = getTemplateRoot(data.minUI5Version);
|
package/dist/section/index.js
CHANGED
|
@@ -85,7 +85,7 @@ async function generate(basePath, customSection, manifestTemplateRoot, fs) {
|
|
|
85
85
|
(0, validate_1.validateVersion)(customSection.minUI5Version);
|
|
86
86
|
fs ??= (0, mem_fs_editor_1.create)((0, mem_fs_1.create)());
|
|
87
87
|
await (0, validate_1.validateBasePath)(basePath, fs);
|
|
88
|
-
const fnGenerateId = await (0, file_1.createIdGenerator)(basePath, fs);
|
|
88
|
+
const fnGenerateId = await (0, file_1.createIdGenerator)({ basePath, fsEditor: fs });
|
|
89
89
|
const { path: manifestPath, content: manifest } = await (0, utils_1.getManifest)(basePath, fs);
|
|
90
90
|
// merge with defaults
|
|
91
91
|
const completeSection = enhanceConfig(fs, customSection, manifestPath, manifest, fnGenerateId);
|
|
@@ -113,7 +113,7 @@ async function generate(basePath, customSection, manifestTemplateRoot, fs) {
|
|
|
113
113
|
*/
|
|
114
114
|
async function generateCustomHeaderSection(basePath, customHeaderSection, fs) {
|
|
115
115
|
const fsEditor = fs ?? (0, mem_fs_editor_1.create)((0, mem_fs_1.create)());
|
|
116
|
-
const fnGenerateId = await (0, file_1.createIdGenerator)(basePath, fsEditor); // initialize ID generator to ensure unique IDs across both section and edit fragment
|
|
116
|
+
const fnGenerateId = await (0, file_1.createIdGenerator)({ basePath, fsEditor }); // initialize ID generator to ensure unique IDs across both section and edit fragment
|
|
117
117
|
const manifestRoot = getManifestRoot('header-section', customHeaderSection.minUI5Version);
|
|
118
118
|
const minVersion = (0, semver_1.coerce)(customHeaderSection.minUI5Version);
|
|
119
119
|
let editSection;
|
package/dist/view/index.js
CHANGED
|
@@ -85,7 +85,7 @@ async function generateCustomView(basePath, customView, fs) {
|
|
|
85
85
|
(0, validate_1.validateVersion)(customView.minUI5Version);
|
|
86
86
|
fs ??= (0, mem_fs_editor_1.create)((0, mem_fs_1.create)());
|
|
87
87
|
await (0, validate_1.validateBasePath)(basePath, fs);
|
|
88
|
-
const fnGenerateId = await (0, file_1.createIdGenerator)(basePath, fs);
|
|
88
|
+
const fnGenerateId = await (0, file_1.createIdGenerator)({ basePath, fsEditor: fs });
|
|
89
89
|
const { path: manifestPath, content: manifest } = await (0, utils_1.getManifest)(basePath, fs);
|
|
90
90
|
// merge with defaults
|
|
91
91
|
const completeView = enhanceConfig(fs, customView, manifestPath, manifest, fnGenerateId);
|
package/package.json
CHANGED