@sap-ux/fe-fpm-writer 0.14.1 → 0.15.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.
@@ -9,6 +9,7 @@ const ejs_1 = require("ejs");
9
9
  const validate_1 = require("../common/validate");
10
10
  const defaults_1 = require("../common/defaults");
11
11
  const event_handler_1 = require("../common/event-handler");
12
+ const templates_1 = require("../templates");
12
13
  /**
13
14
  * Enhances the provided custom action configuration with default data.
14
15
  *
@@ -74,14 +75,13 @@ function generateCustomAction(basePath, actionConfig, fs) {
74
75
  const manifestPath = path_1.join(basePath, 'webapp/manifest.json');
75
76
  const manifest = fs.readJSON(manifestPath);
76
77
  const config = enhanceConfig(actionConfig, manifestPath, manifest);
77
- const root = path_1.join(__dirname, '../../templates');
78
78
  // Apply event handler
79
79
  if (config.eventHandler) {
80
- config.eventHandler = event_handler_1.applyEventHandlerConfiguration(fs, root, config, config.eventHandler, false, config.typescript);
80
+ config.eventHandler = event_handler_1.applyEventHandlerConfiguration(fs, config, config.eventHandler, false, config.typescript);
81
81
  }
82
82
  // enhance manifest with action definition and controller reference
83
83
  const actions = enhanceManifestAndGetActionsElementReference(manifest, config.target);
84
- Object.assign(actions, JSON.parse(ejs_1.render(fs.read(path_1.join(root, `action/manifest.action.json`)), config, {})));
84
+ Object.assign(actions, JSON.parse(ejs_1.render(fs.read(templates_1.getTemplatePath(`action/manifest.action.json`)), config, {})));
85
85
  fs.writeJSON(manifestPath, manifest);
86
86
  return fs;
87
87
  }
package/dist/app/index.js CHANGED
@@ -6,6 +6,7 @@ const mem_fs_editor_1 = require("mem-fs-editor");
6
6
  const path_1 = require("path");
7
7
  const semver_1 = require("semver");
8
8
  const defaults_1 = require("../common/defaults");
9
+ const templates_1 = require("../templates");
9
10
  exports.MIN_VERSION = '1.94.0';
10
11
  /**
11
12
  * Enable the flexible programming model for an application.
@@ -69,7 +70,7 @@ function enableFPM(basePath, config = {}, fs) {
69
70
  // replace Component.js
70
71
  if (config.replaceAppComponent) {
71
72
  const ext = config.typescript ? 'ts' : 'js';
72
- const componentTemplate = path_1.join(__dirname, `../../templates/app/Component.${ext}`);
73
+ const componentTemplate = templates_1.getTemplatePath(`/app/Component.${ext}`);
73
74
  fs.copyTpl(componentTemplate, path_1.join(basePath, `webapp/Component.${ext}`), manifest['sap.app']);
74
75
  }
75
76
  return fs;
@@ -31,6 +31,7 @@ const xmldom_1 = require("@xmldom/xmldom");
31
31
  const xpath = __importStar(require("xpath"));
32
32
  const xml_formatter_1 = __importDefault(require("xml-formatter"));
33
33
  const validate_1 = require("../common/validate");
34
+ const templates_1 = require("../templates");
34
35
  /**
35
36
  * Generates a building block into the provided xml view file.
36
37
  *
@@ -109,7 +110,7 @@ function getOrAddMacrosNamespace(ui5XmlDocument) {
109
110
  */
110
111
  function getTemplateDocument(buildingBlockData, viewDocument, fs) {
111
112
  const templateFolderName = buildingBlockData.buildingBlockType;
112
- const templateFilePath = path_1.join(__dirname, `../../templates/building-block/${templateFolderName}/View.xml`);
113
+ const templateFilePath = templates_1.getTemplatePath(`/building-block/${templateFolderName}/View.xml`);
113
114
  const templateContent = ejs_1.render(fs.read(templateFilePath), {
114
115
  macrosNamespace: getOrAddMacrosNamespace(viewDocument),
115
116
  data: buildingBlockData
@@ -8,6 +8,7 @@ const path_1 = require("path");
8
8
  const defaults_1 = require("../common/defaults");
9
9
  const validate_1 = require("../common/validate");
10
10
  const event_handler_1 = require("../common/event-handler");
11
+ const templates_1 = require("../templates");
11
12
  /**
12
13
  * Get the template folder for the given UI5 version.
13
14
  *
@@ -16,13 +17,13 @@ const event_handler_1 = require("../common/event-handler");
16
17
  */
17
18
  function getManifestRoot(ui5Version) {
18
19
  if (ui5Version === undefined || ui5Version >= 1.86) {
19
- return path_1.join(__dirname, '../../templates/column/1.86');
20
+ return templates_1.getTemplatePath('/column/1.86');
20
21
  }
21
22
  else if (ui5Version === 1.85) {
22
- return path_1.join(__dirname, '../../templates/column/1.85');
23
+ return templates_1.getTemplatePath('/column/1.85');
23
24
  }
24
25
  else {
25
- return path_1.join(__dirname, '../../templates/column/1.84');
26
+ return templates_1.getTemplatePath('column/1.84');
26
27
  }
27
28
  }
28
29
  exports.getManifestRoot = getManifestRoot;
@@ -30,19 +31,18 @@ exports.getManifestRoot = getManifestRoot;
30
31
  * Enhances the provided custom table column configuration with default data.
31
32
  *
32
33
  * @param {Editor} fs - the mem-fs editor instance
33
- * @param {string} root - root path
34
34
  * @param {CustomTableColumn} data - a custom column configuration object
35
35
  * @param {string} manifestPath - path to the project's manifest.json
36
36
  * @param {Manifest} manifest - the application manifest
37
37
  * @returns enhanced configuration
38
38
  */
39
- function enhanceConfig(fs, root, data, manifestPath, manifest) {
39
+ function enhanceConfig(fs, data, manifestPath, manifest) {
40
40
  // clone input and set defaults
41
41
  const config = Object.assign({}, data);
42
42
  defaults_1.setCommonDefaults(config, manifestPath, manifest);
43
43
  // Apply event handler
44
44
  if (config.eventHandler) {
45
- config.eventHandler = event_handler_1.applyEventHandlerConfiguration(fs, root, config, config.eventHandler, false, config.typescript);
45
+ config.eventHandler = event_handler_1.applyEventHandlerConfiguration(fs, config, config.eventHandler, false, config.typescript);
46
46
  }
47
47
  // generate column content
48
48
  const content = config.properties && config.properties.length > 0
@@ -67,9 +67,8 @@ function generateCustomColumn(basePath, customColumn, fs) {
67
67
  validate_1.validateBasePath(basePath, fs);
68
68
  const manifestPath = path_1.join(basePath, 'webapp/manifest.json');
69
69
  const manifest = fs.readJSON(manifestPath);
70
- const root = path_1.join(__dirname, '../../templates');
71
70
  // merge with defaults
72
- const completeColumn = enhanceConfig(fs, root, customColumn, manifestPath, manifest);
71
+ const completeColumn = enhanceConfig(fs, customColumn, manifestPath, manifest);
73
72
  // enhance manifest with column definition
74
73
  const manifestRoot = getManifestRoot(customColumn.ui5Version);
75
74
  const filledTemplate = ejs_1.render(fs.read(path_1.join(manifestRoot, `manifest.json`)), completeColumn, {});
@@ -77,7 +76,7 @@ function generateCustomColumn(basePath, customColumn, fs) {
77
76
  // add fragment
78
77
  const viewPath = path_1.join(completeColumn.path, `${completeColumn.name}.fragment.xml`);
79
78
  if (completeColumn.control || !fs.exists(viewPath)) {
80
- fs.copyTpl(path_1.join(root, 'common/Fragment.xml'), viewPath, completeColumn);
79
+ fs.copyTpl(templates_1.getTemplatePath('common/Fragment.xml'), viewPath, completeColumn);
81
80
  }
82
81
  return fs;
83
82
  }
@@ -4,12 +4,11 @@ import type { EventHandlerConfiguration, InternalCustomElement } from '../common
4
4
  * Method creates or updates handler js file and update 'settings.eventHandler' entry with namespace path entry to method.
5
5
  *
6
6
  * @param {Editor} fs - the memfs editor instance
7
- * @param {string} root - the root path
8
7
  * @param {InternalCustomElement} config - configuration
9
8
  * @param {EventHandlerConfiguration | true | string} [eventHandler] - eventHandler for creation
10
9
  * @param {boolean} [controllerSuffix=false] - append controller suffix to new file
11
10
  * @param {boolean} typescript - create Typescript file instead of Javascript
12
11
  * @returns {string} full namespace path to method
13
12
  */
14
- export declare function applyEventHandlerConfiguration(fs: Editor, root: string, config: Partial<InternalCustomElement>, eventHandler: EventHandlerConfiguration | true | string, controllerSuffix?: boolean, typescript?: boolean): string;
13
+ export declare function applyEventHandlerConfiguration(fs: Editor, config: Partial<InternalCustomElement>, eventHandler: EventHandlerConfiguration | true | string, controllerSuffix?: boolean, typescript?: boolean): string;
15
14
  //# sourceMappingURL=event-handler.d.ts.map
@@ -2,19 +2,19 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.applyEventHandlerConfiguration = void 0;
4
4
  const path_1 = require("path");
5
+ const templates_1 = require("../templates");
5
6
  const utils_1 = require("../common/utils");
6
7
  /**
7
8
  * Method creates or updates handler js file and update 'settings.eventHandler' entry with namespace path entry to method.
8
9
  *
9
10
  * @param {Editor} fs - the memfs editor instance
10
- * @param {string} root - the root path
11
11
  * @param {InternalCustomElement} config - configuration
12
12
  * @param {EventHandlerConfiguration | true | string} [eventHandler] - eventHandler for creation
13
13
  * @param {boolean} [controllerSuffix=false] - append controller suffix to new file
14
14
  * @param {boolean} typescript - create Typescript file instead of Javascript
15
15
  * @returns {string} full namespace path to method
16
16
  */
17
- function applyEventHandlerConfiguration(fs, root, config, eventHandler, controllerSuffix = false, typescript) {
17
+ function applyEventHandlerConfiguration(fs, config, eventHandler, controllerSuffix = false, typescript) {
18
18
  if (typeof eventHandler === 'string') {
19
19
  // Existing event handler is passed - no need for file creation/update
20
20
  return eventHandler;
@@ -37,7 +37,7 @@ function applyEventHandlerConfiguration(fs, root, config, eventHandler, controll
37
37
  const ext = typescript ? 'ts' : 'js';
38
38
  const controllerPath = path_1.join(config.path || '', `${fileName}${controllerSuffix ? '.controller' : ''}.${ext}`);
39
39
  if (!fs.exists(controllerPath)) {
40
- fs.copyTpl(path_1.join(root, `common/EventHandler.${ext}`), controllerPath, {
40
+ fs.copyTpl(templates_1.getTemplatePath(`common/EventHandler.${ext}`), controllerPath, {
41
41
  eventHandlerFnName
42
42
  });
43
43
  }
@@ -0,0 +1,14 @@
1
+ import type { Editor } from 'mem-fs-editor';
2
+ import type { ControllerExtension } from './types';
3
+ export declare const UI5_CONTROLLER_EXTENSION_LIST_REPORT = "sap.fe.templates.ListReport.ListReportController";
4
+ export declare const UI5_CONTROLLER_EXTENSION_OBJECT_PAGE = "sap.fe.templates.ObjectPage.ObjectPageController";
5
+ /**
6
+ * Add a controller extension to an existing UI5 application.
7
+ *
8
+ * @param {string} basePath - the base path
9
+ * @param {ControllerExtension} controllerConfig - the controller extension configuration
10
+ * @param {Editor} [fs] - the memfs editor instance
11
+ * @returns {Editor} the updated memfs editor instance
12
+ */
13
+ export declare function generateControllerExtension(basePath: string, controllerConfig: ControllerExtension, fs?: Editor): Editor;
14
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,195 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.generateControllerExtension = exports.UI5_CONTROLLER_EXTENSION_OBJECT_PAGE = exports.UI5_CONTROLLER_EXTENSION_LIST_REPORT = void 0;
4
+ const mem_fs_1 = require("mem-fs");
5
+ const mem_fs_editor_1 = require("mem-fs-editor");
6
+ const path_1 = require("path");
7
+ const ejs_1 = require("ejs");
8
+ const types_1 = require("./types");
9
+ const validate_1 = require("../common/validate");
10
+ const defaults_1 = require("../common/defaults");
11
+ const templates_1 = require("../templates");
12
+ exports.UI5_CONTROLLER_EXTENSION_LIST_REPORT = 'sap.fe.templates.ListReport.ListReportController';
13
+ exports.UI5_CONTROLLER_EXTENSION_OBJECT_PAGE = 'sap.fe.templates.ObjectPage.ObjectPageController';
14
+ const UI5_CONTROLLER_EXTENSIONS = 'sap.ui.controllerExtensions';
15
+ const EXTENSION_PAGE_TYPE_MAP = new Map([
16
+ [types_1.ControllerExtensionPageType.ListReport, exports.UI5_CONTROLLER_EXTENSION_LIST_REPORT],
17
+ [types_1.ControllerExtensionPageType.ObjectPage, exports.UI5_CONTROLLER_EXTENSION_OBJECT_PAGE]
18
+ ]);
19
+ /**
20
+ * A function appends passed array of values with new value if value does not exist in array.
21
+ *
22
+ * @param values - array of values
23
+ * @param value - value to append
24
+ * @returns Array of values
25
+ */
26
+ function appendUniqueEntryToArray(values, value) {
27
+ if (!values.includes(value)) {
28
+ values.push(value);
29
+ }
30
+ return values;
31
+ }
32
+ /**
33
+ * A function returns existing controller extension from manifest for passed extension id.
34
+ *
35
+ * @param {Manifest} manifest - manifest
36
+ * @param {string} extensionId - extension id
37
+ * @returns {ManifestControllerExtension | undefined} Existing controller extension
38
+ */
39
+ function getExistingControllerExtension(manifest, extensionId) {
40
+ var _a, _b, _c;
41
+ const extensions = (_c = (_b = (_a = manifest['sap.ui5']) === null || _a === void 0 ? void 0 : _a.extends) === null || _b === void 0 ? void 0 : _b.extensions) === null || _c === void 0 ? void 0 : _c[UI5_CONTROLLER_EXTENSIONS];
42
+ if (extensions === null || extensions === void 0 ? void 0 : extensions.hasOwnProperty(extensionId)) {
43
+ return extensions[extensionId];
44
+ }
45
+ return undefined;
46
+ }
47
+ /**
48
+ * Method enhances the provided controller extension by handling existing controller extension entry from manifest.
49
+ * Logic applies following:
50
+ * 1. Handles public property "overwrite" - if we should append or overwrite existing controller names.
51
+ * 2. Detects transition from "controllerName" to "controllerNames" when new controller is appended to exiusting entry with property "controllerNames".
52
+ * 3. Adds new controller entry to "controllerNames" array.
53
+ *
54
+ * @param {ManifestControllerExtension} manifestExtension - controller extension from manifest
55
+ * @param {InternalControllerExtension} config - internal controller extension configuration
56
+ * @param {string} controllerName - full name of new controller to add or replace/overwrite
57
+ */
58
+ function handleExistingManifestExtension(manifestExtension, config, controllerName) {
59
+ if (config.overwrite) {
60
+ if (manifestExtension.controllerNames) {
61
+ // Delete "controllerNames" from manifest because it will be overwritten by single controllerName
62
+ config.deleteProperty = 'controllerNames';
63
+ }
64
+ // Do not need append new controller with existing - exit further handling
65
+ return;
66
+ }
67
+ // Append new controller extension with existing controllers
68
+ if (manifestExtension.controllerName && manifestExtension.controllerName !== config.controllerName) {
69
+ // Manifest has single controller - transfer it into array
70
+ config.controllerNames = manifestExtension.controllerNames ? [...manifestExtension.controllerNames] : [];
71
+ // Check before append
72
+ appendUniqueEntryToArray(config.controllerNames, manifestExtension.controllerName);
73
+ appendUniqueEntryToArray(config.controllerNames, controllerName);
74
+ // Delete "controllerName" from manifest
75
+ config.deleteProperty = 'controllerName';
76
+ }
77
+ else if (manifestExtension.controllerNames && !manifestExtension.controllerNames.includes(controllerName)) {
78
+ // Manifest has array of controllers - append new entry
79
+ config.controllerNames = appendUniqueEntryToArray([...manifestExtension.controllerNames], controllerName);
80
+ }
81
+ }
82
+ /**
83
+ * Method enhances the provided controller extension configuration with default and additional data.
84
+ *
85
+ * @param {string} extensionName - a controller extension configuration object
86
+ * @returns {ControllerExtensionPageTarget | undefined} Page configuration object if extension name is assigned to supported page type.
87
+ */
88
+ function resolvePageDataFromExtension(extensionName) {
89
+ for (const [key, value] of EXTENSION_PAGE_TYPE_MAP) {
90
+ if (extensionName.startsWith(value)) {
91
+ return {
92
+ pageType: key
93
+ };
94
+ }
95
+ }
96
+ return undefined;
97
+ }
98
+ /**
99
+ * Method enhances the provided controller extension configuration with default and additional data.
100
+ *
101
+ * @param {ControllerExtension} data - a controller extension configuration object
102
+ * @param {string} manifestPath - path to the project's manifest.json
103
+ * @param {Manifest} manifest - the application manifest
104
+ * @returns enhanced configuration
105
+ */
106
+ function enhanceConfig(data, manifestPath, manifest) {
107
+ // clone input
108
+ const config = Object.assign({}, data);
109
+ // Apply default data
110
+ defaults_1.setCommonDefaults(config, manifestPath, manifest);
111
+ // Create `controllerName` with full path/namespace
112
+ config.controllerName = `${config.ns}.${config.name}`;
113
+ // Resolve controller extension id/key
114
+ let extensionId;
115
+ if (typeof config.extension === 'object') {
116
+ // Use default as List Report
117
+ config.extension.pageType = config.extension.pageType || types_1.ControllerExtensionPageType.ListReport;
118
+ const { pageType, pageId } = config.extension;
119
+ extensionId = EXTENSION_PAGE_TYPE_MAP.get(pageType) || exports.UI5_CONTROLLER_EXTENSION_LIST_REPORT;
120
+ if (pageId) {
121
+ // Prepend project id
122
+ extensionId = `${extensionId}#${manifest['sap.app'].id}::${pageId}`;
123
+ }
124
+ }
125
+ else {
126
+ // Try to resolve page type from manual extension
127
+ extensionId = config.extension;
128
+ config.extension = resolvePageDataFromExtension(config.extension) || config.extension;
129
+ }
130
+ config.extensionId = extensionId;
131
+ // Get existing controller extension entry from manifest
132
+ const manifestExtension = getExistingControllerExtension(manifest, extensionId);
133
+ // If controller extension already exists in manifest - append new controller
134
+ if (manifestExtension) {
135
+ handleExistingManifestExtension(manifestExtension, config, config.controllerName);
136
+ }
137
+ return config;
138
+ }
139
+ /**
140
+ * A function that transforms JSON object during JSON.stringify call.
141
+ * Method is used to remove 'controllerName' or 'controllerNames' properties from manifest in case when we have transition from 'controllerName' to 'controllerNames'.
142
+ *
143
+ * @param {InternalControllerExtension} config - a controller extension configuration object
144
+ * @returns Json replacer method
145
+ */
146
+ function getManifestReplacer(config) {
147
+ let isRoot = true;
148
+ const { deleteProperty } = config;
149
+ if (!deleteProperty) {
150
+ // No request to delete any property
151
+ return undefined;
152
+ }
153
+ return (key, value) => {
154
+ // Handle only root - more stable solution instead of checking 'key'
155
+ if (key === '' && isRoot) {
156
+ isRoot = false;
157
+ const extension = getExistingControllerExtension(value, config.extensionId);
158
+ if (extension) {
159
+ delete extension[deleteProperty];
160
+ }
161
+ }
162
+ return value;
163
+ };
164
+ }
165
+ /**
166
+ * Add a controller extension to an existing UI5 application.
167
+ *
168
+ * @param {string} basePath - the base path
169
+ * @param {ControllerExtension} controllerConfig - the controller extension configuration
170
+ * @param {Editor} [fs] - the memfs editor instance
171
+ * @returns {Editor} the updated memfs editor instance
172
+ */
173
+ function generateControllerExtension(basePath, controllerConfig, fs) {
174
+ // Validate the base and view paths
175
+ if (!fs) {
176
+ fs = mem_fs_editor_1.create(mem_fs_1.create());
177
+ }
178
+ validate_1.validateBasePath(basePath, fs);
179
+ const manifestPath = path_1.join(basePath, 'webapp/manifest.json');
180
+ const manifest = fs.readJSON(manifestPath);
181
+ // merge with defaults
182
+ const internalConfig = enhanceConfig(controllerConfig, manifestPath, manifest);
183
+ // enhance manifest with view definition
184
+ const filledTemplate = ejs_1.render(fs.read(templates_1.getTemplatePath('controller-extension/manifest.json')), internalConfig, {});
185
+ fs.extendJSON(manifestPath, JSON.parse(filledTemplate), getManifestReplacer(internalConfig));
186
+ // add controller js file
187
+ const ext = controllerConfig.typescript ? 'ts' : 'js';
188
+ const viewPath = path_1.join(internalConfig.path, `${internalConfig.name}.controller.${ext}`);
189
+ if (!fs.exists(viewPath)) {
190
+ fs.copyTpl(templates_1.getTemplatePath(`controller-extension/Controller.${ext}`), viewPath, internalConfig);
191
+ }
192
+ return fs;
193
+ }
194
+ exports.generateControllerExtension = generateControllerExtension;
195
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,61 @@
1
+ import type { CustomElement, InternalCustomElement } from '../common/types';
2
+ /**
3
+ * Controller extension's associated page type.
4
+ *
5
+ * @enum {string}
6
+ */
7
+ export declare enum ControllerExtensionPageType {
8
+ ObjectPage = "ObjectPage",
9
+ ListReport = "ListReport"
10
+ }
11
+ /**
12
+ * Target page configuration for controller extension.
13
+ */
14
+ export interface ControllerExtensionPageTarget {
15
+ /**
16
+ * The page type for which controller extension should be triggered.
17
+ */
18
+ pageType: ControllerExtensionPageType;
19
+ /**
20
+ * The unique page id for which controller extension should be triggered.
21
+ */
22
+ pageId?: string;
23
+ }
24
+ /**
25
+ * Controller extension configuration for the generate function.
26
+ */
27
+ export interface ControllerExtension extends CustomElement {
28
+ /**
29
+ * Property to define extension entry point.
30
+ * Provide any extension name as string or use page configuration.
31
+ */
32
+ extension: ControllerExtensionPageTarget | string;
33
+ /**
34
+ * Controls if controller(s) for existing controller extension should be appended or replaced with new controller.
35
+ */
36
+ overwrite?: boolean;
37
+ }
38
+ /**
39
+ * Represents a controller extension configuration in manifest.
40
+ */
41
+ export interface ManifestControllerExtension {
42
+ /**
43
+ * Specifies single controller for controller extension.
44
+ */
45
+ controllerName?: string;
46
+ /**
47
+ * Specifies multiple controllers for controller extension.
48
+ */
49
+ controllerNames?: string[];
50
+ }
51
+ export interface InternalControllerExtension extends ControllerExtension, ManifestControllerExtension, InternalCustomElement {
52
+ /**
53
+ * Derived full extension key/id in manifest "sap.ui.controllerExtensions" object.
54
+ */
55
+ extensionId: string;
56
+ /**
57
+ * Delete property from existing control extension object in manifest.
58
+ */
59
+ deleteProperty?: keyof ManifestControllerExtension;
60
+ }
61
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ControllerExtensionPageType = void 0;
4
+ /**
5
+ * Controller extension's associated page type.
6
+ *
7
+ * @enum {string}
8
+ */
9
+ var ControllerExtensionPageType;
10
+ (function (ControllerExtensionPageType) {
11
+ ControllerExtensionPageType["ObjectPage"] = "ObjectPage";
12
+ ControllerExtensionPageType["ListReport"] = "ListReport";
13
+ })(ControllerExtensionPageType = exports.ControllerExtensionPageType || (exports.ControllerExtensionPageType = {}));
14
+ //# sourceMappingURL=types.js.map
package/dist/index.d.ts CHANGED
@@ -12,4 +12,6 @@ export { enableFPM, FPMConfig } from './app';
12
12
  export { validateBasePath, validateVersion } from './common/validate';
13
13
  export { BuildingBlockType, FilterBar, Chart, Field, FieldFormatOptions } from './building-block/types';
14
14
  export { generateBuildingBlock } from './building-block';
15
+ export { ControllerExtension, ControllerExtensionPageType } from './controller-extension/types';
16
+ export { generateControllerExtension } from './controller-extension';
15
17
  //# sourceMappingURL=index.d.ts.map
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.generateBuildingBlock = exports.BuildingBlockType = exports.validateVersion = exports.validateBasePath = exports.enableFPM = exports.generateCustomView = exports.generateCustomSection = exports.generateCustomColumn = exports.generateCustomAction = exports.TargetControl = exports.generateListReport = exports.generateObjectPage = exports.generateCustomPage = void 0;
3
+ exports.generateControllerExtension = exports.ControllerExtensionPageType = exports.generateBuildingBlock = exports.BuildingBlockType = exports.validateVersion = exports.validateBasePath = exports.enableFPM = exports.generateCustomView = exports.generateCustomSection = exports.generateCustomColumn = 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; } });
@@ -24,4 +24,8 @@ var types_2 = require("./building-block/types");
24
24
  Object.defineProperty(exports, "BuildingBlockType", { enumerable: true, get: function () { return types_2.BuildingBlockType; } });
25
25
  var building_block_1 = require("./building-block");
26
26
  Object.defineProperty(exports, "generateBuildingBlock", { enumerable: true, get: function () { return building_block_1.generateBuildingBlock; } });
27
+ var types_3 = require("./controller-extension/types");
28
+ Object.defineProperty(exports, "ControllerExtensionPageType", { enumerable: true, get: function () { return types_3.ControllerExtensionPageType; } });
29
+ var controller_extension_1 = require("./controller-extension");
30
+ Object.defineProperty(exports, "generateControllerExtension", { enumerable: true, get: function () { return controller_extension_1.generateControllerExtension; } });
27
31
  //# sourceMappingURL=index.js.map
@@ -8,6 +8,7 @@ const ejs_1 = require("ejs");
8
8
  const common_1 = require("./common");
9
9
  const defaults_1 = require("../common/defaults");
10
10
  const validate_1 = require("../common/validate");
11
+ const templates_1 = require("../templates");
11
12
  /**
12
13
  * Enhances the provided custom page configuration with default data.
13
14
  *
@@ -40,10 +41,10 @@ exports.enhanceData = enhanceData;
40
41
  */
41
42
  function getTemplateRoot(ui5Version) {
42
43
  if (ui5Version === undefined || ui5Version >= 1.94) {
43
- return path_1.join(__dirname, '../../templates/page/custom/1.94');
44
+ return templates_1.getTemplatePath('/page/custom/1.94');
44
45
  }
45
46
  else {
46
- return path_1.join(__dirname, '../../templates/page/custom/1.84');
47
+ return templates_1.getTemplatePath('/page/custom/1.84');
47
48
  }
48
49
  }
49
50
  exports.getTemplateRoot = getTemplateRoot;
package/dist/page/list.js CHANGED
@@ -6,6 +6,7 @@ const mem_fs_1 = require("mem-fs");
6
6
  const mem_fs_editor_1 = require("mem-fs-editor");
7
7
  const ejs_1 = require("ejs");
8
8
  const common_1 = require("./common");
9
+ const templates_1 = require("../templates");
9
10
  /**
10
11
  * Enhances the provided list report configuration with default data.
11
12
  *
@@ -50,7 +51,7 @@ function generate(basePath, data, fs) {
50
51
  const manifest = fs.readJSON(manifestPath);
51
52
  const config = enhanceData(data, manifest);
52
53
  // enhance manifest.json
53
- fs.extendJSON(manifestPath, JSON.parse(ejs_1.render(fs.read(path_1.join(__dirname, '../../templates/page/list/manifest.json')), config, {})), common_1.getManifestJsonExtensionHelper(config));
54
+ fs.extendJSON(manifestPath, JSON.parse(ejs_1.render(fs.read(templates_1.getTemplatePath('page/list/manifest.json')), config, {})), common_1.getManifestJsonExtensionHelper(config));
54
55
  return fs;
55
56
  }
56
57
  exports.generate = generate;
@@ -6,6 +6,7 @@ const mem_fs_1 = require("mem-fs");
6
6
  const mem_fs_editor_1 = require("mem-fs-editor");
7
7
  const ejs_1 = require("ejs");
8
8
  const common_1 = require("./common");
9
+ const templates_1 = require("../templates");
9
10
  /**
10
11
  * Enhances the provided list report configuration with default data.
11
12
  *
@@ -41,7 +42,7 @@ function generate(basePath, data, fs) {
41
42
  const manifest = fs.readJSON(manifestPath);
42
43
  const config = enhanceData(data, manifest);
43
44
  // enhance manifest.json
44
- fs.extendJSON(manifestPath, JSON.parse(ejs_1.render(fs.read(path_1.join(__dirname, '../../templates/page/object/manifest.json')), config, {})), common_1.getManifestJsonExtensionHelper(config));
45
+ fs.extendJSON(manifestPath, JSON.parse(ejs_1.render(fs.read(templates_1.getTemplatePath('/page/object/manifest.json')), config, {})), common_1.getManifestJsonExtensionHelper(config));
45
46
  return fs;
46
47
  }
47
48
  exports.generate = generate;
@@ -3,11 +3,10 @@ import type { CustomSection } from './types';
3
3
  /**
4
4
  * Get the template folder for the given UI5 version.
5
5
  *
6
- * @param root root path to templates folder.
7
6
  * @param ui5Version required UI5 version.
8
7
  * @returns path to the template folder containing the manifest.json ejs template
9
8
  */
10
- export declare function getManifestRoot(root: string, ui5Version?: number): string;
9
+ export declare function getManifestRoot(ui5Version?: number): string;
11
10
  /**
12
11
  * Add a custom section to an existing UI5 application.
13
12
  *
@@ -8,38 +8,37 @@ const ejs_1 = require("ejs");
8
8
  const validate_1 = require("../common/validate");
9
9
  const defaults_1 = require("../common/defaults");
10
10
  const event_handler_1 = require("../common/event-handler");
11
+ const templates_1 = require("../templates");
11
12
  /**
12
13
  * Get the template folder for the given UI5 version.
13
14
  *
14
- * @param root root path to templates folder.
15
15
  * @param ui5Version required UI5 version.
16
16
  * @returns path to the template folder containing the manifest.json ejs template
17
17
  */
18
- function getManifestRoot(root, ui5Version) {
18
+ function getManifestRoot(ui5Version) {
19
19
  let subFolder = '1.86';
20
20
  if (ui5Version !== undefined && ui5Version < 1.86) {
21
21
  // Old
22
22
  subFolder = '1.85';
23
23
  }
24
- return path_1.join(root, 'section', subFolder);
24
+ return templates_1.getTemplatePath(path_1.join('section', subFolder));
25
25
  }
26
26
  exports.getManifestRoot = getManifestRoot;
27
27
  /**
28
28
  * Enhances the provided custom section configuration with additonal data.
29
29
  *
30
30
  * @param {Editor} fs - the mem-fs editor instance
31
- * @param {string} root - root path
32
31
  * @param {CustomSection} data - a custom section configuration object
33
32
  * @param {string} manifestPath - path to the project's manifest.json
34
33
  * @param {Manifest} manifest - the application manifest
35
34
  * @returns enhanced configuration
36
35
  */
37
- function enhanceConfig(fs, root, data, manifestPath, manifest) {
36
+ function enhanceConfig(fs, data, manifestPath, manifest) {
38
37
  const config = Object.assign({}, data);
39
38
  defaults_1.setCommonDefaults(config, manifestPath, manifest);
40
39
  // Apply event handler
41
40
  if (config.eventHandler) {
42
- config.eventHandler = event_handler_1.applyEventHandlerConfiguration(fs, root, config, config.eventHandler, false, config.typescript);
41
+ config.eventHandler = event_handler_1.applyEventHandlerConfiguration(fs, config, config.eventHandler, false, config.typescript);
43
42
  }
44
43
  // generate section content
45
44
  config.content = config.control || defaults_1.getDefaultFragmentContent(config.name, config.eventHandler);
@@ -61,17 +60,16 @@ function generateCustomSection(basePath, customSection, fs) {
61
60
  validate_1.validateBasePath(basePath, fs);
62
61
  const manifestPath = path_1.join(basePath, 'webapp/manifest.json');
63
62
  const manifest = fs.readJSON(manifestPath);
64
- const root = path_1.join(__dirname, '../../templates');
65
63
  // merge with defaults
66
- const completeSection = enhanceConfig(fs, root, customSection, manifestPath, manifest);
64
+ const completeSection = enhanceConfig(fs, customSection, manifestPath, manifest);
67
65
  // enhance manifest with section definition
68
- const manifestRoot = getManifestRoot(root, customSection.ui5Version);
66
+ const manifestRoot = getManifestRoot(customSection.ui5Version);
69
67
  const filledTemplate = ejs_1.render(fs.read(path_1.join(manifestRoot, `manifest.json`)), completeSection, {});
70
68
  fs.extendJSON(manifestPath, JSON.parse(filledTemplate));
71
69
  // add fragment
72
70
  const viewPath = path_1.join(completeSection.path, `${completeSection.name}.fragment.xml`);
73
71
  if (!fs.exists(viewPath)) {
74
- fs.copyTpl(path_1.join(root, 'common/Fragment.xml'), viewPath, completeSection);
72
+ fs.copyTpl(templates_1.getTemplatePath('common/Fragment.xml'), viewPath, completeSection);
75
73
  }
76
74
  return fs;
77
75
  }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Locates template files relative to the dist folder.
3
+ * This helps to locate templates when this module is bundled and the dir structure is flattened, maintaining the relative paths.
4
+ *
5
+ * @param relativeTemplatePath - optional, the path of the required template relative to the ./templates folder. If not specified the root templates folder is returned.
6
+ * @returns the path of the template specified or templates root folder
7
+ */
8
+ export declare function getTemplatePath(relativeTemplatePath?: string): string;
9
+ //# sourceMappingURL=templates.d.ts.map
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getTemplatePath = void 0;
4
+ const path_1 = require("path");
5
+ /**
6
+ * Locates template files relative to the dist folder.
7
+ * This helps to locate templates when this module is bundled and the dir structure is flattened, maintaining the relative paths.
8
+ *
9
+ * @param relativeTemplatePath - optional, the path of the required template relative to the ./templates folder. If not specified the root templates folder is returned.
10
+ * @returns the path of the template specified or templates root folder
11
+ */
12
+ function getTemplatePath(relativeTemplatePath = '') {
13
+ return path_1.join(__dirname, '../templates', relativeTemplatePath);
14
+ }
15
+ exports.getTemplatePath = getTemplatePath;
16
+ //# sourceMappingURL=templates.js.map
@@ -8,23 +8,23 @@ const ejs_1 = require("ejs");
8
8
  const validate_1 = require("../common/validate");
9
9
  const defaults_1 = require("../common/defaults");
10
10
  const event_handler_1 = require("../common/event-handler");
11
+ const templates_1 = require("../templates");
11
12
  /**
12
13
  * Enhances the provided custom view configuration with default data.
13
14
  *
14
15
  * @param {Editor} fs - the mem-fs editor instance
15
- * @param {string} root - root path
16
16
  * @param {CustomView} data - a custom view configuration object
17
17
  * @param {string} manifestPath - path to the project's manifest.json
18
18
  * @param {Manifest} manifest - the application manifest
19
19
  * @returns enhanced configuration
20
20
  */
21
- function enhanceConfig(fs, root, data, manifestPath, manifest) {
21
+ function enhanceConfig(fs, data, manifestPath, manifest) {
22
22
  var _a, _b, _c, _d, _e;
23
23
  const config = Object.assign({}, data);
24
24
  defaults_1.setCommonDefaults(config, manifestPath, manifest);
25
25
  // Apply event handler
26
26
  if (config.eventHandler) {
27
- config.eventHandler = event_handler_1.applyEventHandlerConfiguration(fs, root, config, config.eventHandler, true, config.typescript);
27
+ config.eventHandler = event_handler_1.applyEventHandlerConfiguration(fs, config, config.eventHandler, true, config.typescript);
28
28
  }
29
29
  // existing views
30
30
  const existingViews = (_e = (_d = ((_c = (_b = (_a = manifest['sap.ui5']) === null || _a === void 0 ? void 0 : _a.routing) === null || _b === void 0 ? void 0 : _b.targets) === null || _c === void 0 ? void 0 : _c[data.target])
@@ -57,19 +57,18 @@ function generateCustomView(basePath, customView, fs) {
57
57
  validate_1.validateBasePath(basePath, fs);
58
58
  const manifestPath = path_1.join(basePath, 'webapp/manifest.json');
59
59
  const manifest = fs.readJSON(manifestPath);
60
- const root = path_1.join(__dirname, '../../templates');
61
60
  // merge with defaults
62
- const completeView = enhanceConfig(fs, root, customView, manifestPath, manifest);
61
+ const completeView = enhanceConfig(fs, customView, manifestPath, manifest);
63
62
  // enhance manifest with view definition
64
- const filledTemplate = ejs_1.render(fs.read(path_1.join(root, 'view', `manifest.json`)), completeView, {});
63
+ const filledTemplate = ejs_1.render(fs.read(templates_1.getTemplatePath('view/manifest.json')), completeView, {});
65
64
  fs.extendJSON(manifestPath, JSON.parse(filledTemplate));
66
65
  // add fragment
67
66
  const viewPath = path_1.join(completeView.path, `${completeView.name}.fragment.xml`);
68
67
  if (completeView.control === true) {
69
- fs.copyTpl(path_1.join(root, 'view/ext/CustomViewWithTable.xml'), viewPath, completeView);
68
+ fs.copyTpl(templates_1.getTemplatePath('view/ext/CustomViewWithTable.xml'), viewPath, completeView);
70
69
  }
71
70
  else if (!fs.exists(viewPath)) {
72
- fs.copyTpl(path_1.join(root, 'common/Fragment.xml'), viewPath, completeView);
71
+ fs.copyTpl(templates_1.getTemplatePath('common/Fragment.xml'), viewPath, completeView);
73
72
  }
74
73
  return fs;
75
74
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@sap-ux/fe-fpm-writer",
3
3
  "description": "SAP Fiori elements flexible programming model writer",
4
- "version": "0.14.1",
4
+ "version": "0.15.0",
5
5
  "repository": {
6
6
  "type": "git",
7
7
  "url": "https://github.com/SAP/open-ux-tools.git",
@@ -9,14 +9,5 @@ sap.ui.define(
9
9
  metadata: {
10
10
  manifest: "json"
11
11
  }
12
-
13
- /**
14
- * The component is initialized by UI5 automatically during the startup of the app and calls the init method once.
15
- * @public
16
- * @override
17
- */
18
- //init: function() {
19
- // AppComponent.prototype.init.apply(this, arguments);
20
- //}
21
12
  });
22
13
  });
@@ -1,20 +1,11 @@
1
1
  import AppComponent from 'sap/fe/core/AppComponent';
2
2
 
3
3
  /**
4
- * @namespace <%- app.id %>
4
+ * @namespace <%- id %>
5
5
  */
6
6
  export default class Component extends AppComponent {
7
7
 
8
8
  public static metadata = {
9
9
  manifest: "json"
10
10
  };
11
-
12
- /**
13
- * The component is initialized by UI5 automatically during the startup of the app and calls the init method once.
14
- * @public
15
- * @override
16
- */
17
- //public init() : void {
18
- // super.init();
19
- //}
20
- }
11
+ }
@@ -0,0 +1,18 @@
1
+ sap.ui.define(['sap/ui/core/mvc/ControllerExtension'], function (ControllerExtension) {
2
+ 'use strict';
3
+
4
+ return ControllerExtension.extend('<%- ns %>.<%- name %>', {
5
+ // this section allows to extend lifecycle hooks or hooks provided by Fiori elements
6
+ override: {
7
+ /**
8
+ * Called when a controller is instantiated and its View controls (if available) are already created.
9
+ * Can be used to modify the View before it is displayed, to bind event handlers and do other one-time initialization.
10
+ * @memberOf <%- ns %>.<%- name %>
11
+ */
12
+ onInit: function () {
13
+ // you can access the Fiori elements extensionAPI via this.base.getExtensionAPI
14
+ var oModel = this.base.getExtensionAPI().getModel();
15
+ }
16
+ }
17
+ });
18
+ });
@@ -0,0 +1,26 @@
1
+ import ControllerExtension from 'sap/ui/core/mvc/ControllerExtension';
2
+ import ExtensionAPI from 'sap/fe/<%- typeof extension === "object" ? `templates/${extension.pageType}` : "core" -%>/ExtensionAPI';
3
+
4
+ /**
5
+ * Definition of the override interface as workaround until https://github.com/SAP/ui5-typescript/issues/332 is fixed.
6
+ */
7
+ interface ExtensionOverride {
8
+ base: {
9
+ getExtensionAPI(): ExtensionAPI;
10
+ }
11
+ }
12
+
13
+ export default ControllerExtension.extend('<%- ns %>.<%- name %>', {
14
+ // this section allows to extend lifecycle hooks or hooks provided by Fiori elements
15
+ override: {
16
+ /**
17
+ * Called when a controller is instantiated and its View controls (if available) are already created.
18
+ * Can be used to modify the View before it is displayed, to bind event handlers and do other one-time initialization.
19
+ * @memberOf <%- ns %>.<%- name %>
20
+ */
21
+ onInit(this: ExtensionOverride) {
22
+ // you can access the Fiori elements extensionAPI via this.base.getExtensionAPI
23
+ const model = this.base.getExtensionAPI().getModel();
24
+ }
25
+ }
26
+ });
@@ -0,0 +1,14 @@
1
+ {
2
+ "sap.ui5": {
3
+ "extends": {
4
+ "extensions": {
5
+ "sap.ui.controllerExtensions": {
6
+ "<%- extensionId -%>": {<%if (typeof controllerNames !== 'undefined') {%>
7
+ "controllerNames": <%- JSON.stringify(controllerNames) %><% } else {%>
8
+ "controllerName": "<%- controllerName %>"<% } %>
9
+ }
10
+ }
11
+ }
12
+ }
13
+ }
14
+ }