@sap-ux/preview-middleware 0.13.73 → 0.14.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.
@@ -0,0 +1,143 @@
1
+ import type { Logger } from '@sap-ux/logger';
2
+ import { ToolsLogger } from '@sap-ux/logger';
3
+ import type { App, FlpConfig, Intent, InternalTestConfig, MiddlewareConfig } from '../types';
4
+ import { type Manifest, type UI5FlexLayer } from '@sap-ux/project-access';
5
+ import { type Editor } from 'mem-fs-editor';
6
+ export interface CustomConnector {
7
+ applyConnector: string;
8
+ writeConnector: string;
9
+ custom: boolean;
10
+ }
11
+ export interface FlexConnector {
12
+ connector: string;
13
+ layers: string[];
14
+ url?: string;
15
+ }
16
+ /**
17
+ * Internal structure used to fill the sandbox.html template
18
+ */
19
+ export interface TemplateConfig {
20
+ basePath: string;
21
+ apps: Record<string, {
22
+ title: string;
23
+ description: string;
24
+ additionalInformation: string;
25
+ applicationType: 'URL';
26
+ url: string;
27
+ applicationDependencies?: {
28
+ manifest: boolean;
29
+ };
30
+ }>;
31
+ ui5: {
32
+ libs: string;
33
+ theme: string;
34
+ flex: (CustomConnector | FlexConnector)[];
35
+ bootstrapOptions: string;
36
+ resources: Record<string, string>;
37
+ };
38
+ init?: string;
39
+ flex?: {
40
+ [key: string]: unknown;
41
+ layer: UI5FlexLayer;
42
+ developerMode: boolean;
43
+ pluginScript?: string;
44
+ };
45
+ locateReuseLibsScript?: boolean;
46
+ }
47
+ /**
48
+ * Static settings
49
+ */
50
+ export declare const PREVIEW_URL: {
51
+ readonly client: {
52
+ readonly url: "/preview/client";
53
+ readonly local: string;
54
+ readonly ns: "open.ux.preview.client";
55
+ };
56
+ readonly api: "/preview/api";
57
+ };
58
+ /**
59
+ * Default theme
60
+ */
61
+ export declare const DEFAULT_THEME = "sap_horizon";
62
+ /**
63
+ * Default path for mounting the local FLP.
64
+ */
65
+ export declare const DEFAULT_PATH = "/test/flp.html";
66
+ /**
67
+ * Default intent
68
+ */
69
+ export declare const DEFAULT_INTENT: Readonly<Intent>;
70
+ /**
71
+ * Default configuration for the FLP.
72
+ *
73
+ * @param config partial configuration
74
+ * @returns a full configuration with default values
75
+ */
76
+ export declare function getFlpConfigWithDefaults(config?: Partial<FlpConfig>): {
77
+ path: string;
78
+ intent: Readonly<Intent>;
79
+ apps: App[];
80
+ libs: boolean | undefined;
81
+ theme: string | undefined;
82
+ init: string | undefined;
83
+ };
84
+ /**
85
+ * The developer mode is only supported for adaptation projects, therefore, notify the user if it is wrongly configured and then disable it.
86
+ *
87
+ * @param config configurations from the ui5.yaml
88
+ * @param logger logger instance
89
+ */
90
+ export declare function sanitizeConfig(config: MiddlewareConfig, logger: ToolsLogger): void;
91
+ /**
92
+ * Add an application to the local FLP preview.
93
+ *
94
+ * @param templateConfig configuration for the preview
95
+ * @param manifest manifest of the additional target app
96
+ * @param app configuration for the preview
97
+ * @param logger logger instance
98
+ */
99
+ export declare function addApp(templateConfig: TemplateConfig, manifest: Manifest, app: App, logger: Logger): Promise<void>;
100
+ /**
101
+ * Creates the configuration object for the sandbox.html template.
102
+ *
103
+ * @param config FLP configuration
104
+ * @param manifest application manifest
105
+ * @returns configuration object for the sandbox.html template
106
+ */
107
+ export declare function createFlpTemplateConfig(config: FlpConfig, manifest: Manifest): TemplateConfig;
108
+ /**
109
+ * Creates the configuration object for the test template.
110
+ *
111
+ * @param config test configuration
112
+ * @param id application id
113
+ * @returns configuration object for the test template
114
+ */
115
+ export declare function createTestTemplateConfig(config: InternalTestConfig, id: string): {
116
+ id: string;
117
+ framework: "OPA5" | "QUnit" | "Testsuite";
118
+ basePath: string;
119
+ initPath: string;
120
+ };
121
+ export type PreviewUrls = {
122
+ path: string;
123
+ type: 'preview' | 'editor' | 'test';
124
+ };
125
+ /**
126
+ * Returns the preview paths.
127
+ *
128
+ * @param config configuration from the ui5.yaml
129
+ * @param logger logger instance
130
+ * @returns an array of preview paths
131
+ */
132
+ export declare function getPreviewPaths(config: MiddlewareConfig, logger?: ToolsLogger): PreviewUrls[];
133
+ /**
134
+ * Generates the preview files.
135
+ *
136
+ * @param basePath path to the application root
137
+ * @param config configuration from the ui5.yaml
138
+ * @param fs file system editor
139
+ * @param logger logger instance
140
+ * @returns a mem-fs editor with the preview files
141
+ */
142
+ export declare function generatePreviewFiles(basePath: string, config: MiddlewareConfig, fs?: Editor, logger?: ToolsLogger): Promise<Editor>;
143
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1,343 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.generatePreviewFiles = exports.getPreviewPaths = exports.createTestTemplateConfig = exports.createFlpTemplateConfig = exports.addApp = exports.sanitizeConfig = exports.getFlpConfigWithDefaults = exports.DEFAULT_INTENT = exports.DEFAULT_PATH = exports.DEFAULT_THEME = exports.PREVIEW_URL = void 0;
13
+ const logger_1 = require("@sap-ux/logger");
14
+ const ejs_1 = require("ejs");
15
+ const path_1 = require("path");
16
+ const project_access_1 = require("@sap-ux/project-access");
17
+ const fs_1 = require("fs");
18
+ const test_1 = require("./test");
19
+ const mem_fs_editor_1 = require("mem-fs-editor");
20
+ const mem_fs_1 = require("mem-fs");
21
+ /**
22
+ * Static settings
23
+ */
24
+ exports.PREVIEW_URL = {
25
+ client: {
26
+ url: '/preview/client',
27
+ local: (0, path_1.join)(__dirname, '../../dist/client'),
28
+ ns: 'open.ux.preview.client'
29
+ },
30
+ api: '/preview/api'
31
+ };
32
+ /**
33
+ * Default theme
34
+ */
35
+ exports.DEFAULT_THEME = 'sap_horizon';
36
+ /**
37
+ * Default path for mounting the local FLP.
38
+ */
39
+ exports.DEFAULT_PATH = '/test/flp.html';
40
+ /**
41
+ * Default intent
42
+ */
43
+ exports.DEFAULT_INTENT = {
44
+ object: 'app',
45
+ action: 'preview'
46
+ };
47
+ /**
48
+ * SAPUI5 delivered namespaces from https://ui5.sap.com/#/api/sap
49
+ */
50
+ const UI5_LIBS = [
51
+ 'sap.apf',
52
+ 'sap.base',
53
+ 'sap.chart',
54
+ 'sap.collaboration',
55
+ 'sap.f',
56
+ 'sap.fe',
57
+ 'sap.fileviewer',
58
+ 'sap.gantt',
59
+ 'sap.landvisz',
60
+ 'sap.m',
61
+ 'sap.ndc',
62
+ 'sap.ovp',
63
+ 'sap.rules',
64
+ 'sap.suite',
65
+ 'sap.tnt',
66
+ 'sap.ui',
67
+ 'sap.uiext',
68
+ 'sap.ushell',
69
+ 'sap.uxap',
70
+ 'sap.viz',
71
+ 'sap.webanalytics',
72
+ 'sap.zen'
73
+ ];
74
+ /**
75
+ * Gets the UI5 libs dependencies from manifest.json.
76
+ *
77
+ * @param manifest application manifest
78
+ * @returns UI5 libs that should preloaded
79
+ */
80
+ function getUI5Libs(manifest) {
81
+ var _a, _b, _c;
82
+ const libs = (_c = (_b = (_a = manifest['sap.ui5']) === null || _a === void 0 ? void 0 : _a.dependencies) === null || _b === void 0 ? void 0 : _b.libs) !== null && _c !== void 0 ? _c : {};
83
+ // add libs that should always be preloaded
84
+ libs['sap.m'] = {};
85
+ libs['sap.ui.core'] = {};
86
+ libs['sap.ushell'] = {};
87
+ return Object.keys(libs)
88
+ .filter((key) => {
89
+ return UI5_LIBS.some((substring) => {
90
+ return key === substring || key.startsWith(substring + '.');
91
+ });
92
+ })
93
+ .join(',');
94
+ }
95
+ /**
96
+ * Default configuration for the FLP.
97
+ *
98
+ * @param config partial configuration
99
+ * @returns a full configuration with default values
100
+ */
101
+ function getFlpConfigWithDefaults(config = {}) {
102
+ var _a, _b, _c;
103
+ const flpConfig = {
104
+ path: (_a = config.path) !== null && _a !== void 0 ? _a : exports.DEFAULT_PATH,
105
+ intent: (_b = config.intent) !== null && _b !== void 0 ? _b : exports.DEFAULT_INTENT,
106
+ apps: (_c = config.apps) !== null && _c !== void 0 ? _c : [],
107
+ libs: config.libs,
108
+ theme: config.theme,
109
+ init: config.init
110
+ };
111
+ if (!flpConfig.path.startsWith('/')) {
112
+ flpConfig.path = `/${flpConfig.path}`;
113
+ }
114
+ return flpConfig;
115
+ }
116
+ exports.getFlpConfigWithDefaults = getFlpConfigWithDefaults;
117
+ /**
118
+ * The developer mode is only supported for adaptation projects, therefore, notify the user if it is wrongly configured and then disable it.
119
+ *
120
+ * @param config configurations from the ui5.yaml
121
+ * @param logger logger instance
122
+ */
123
+ function sanitizeConfig(config, logger) {
124
+ if (config.rta && config.adp === undefined) {
125
+ config.rta.editors = config.rta.editors.filter((editor) => {
126
+ if (editor.developerMode) {
127
+ logger.error('developerMode is ONLY supported for SAP UI5 adaptation projects.');
128
+ logger.warn(`developerMode for ${editor.path} disabled`);
129
+ }
130
+ return !editor.developerMode;
131
+ });
132
+ }
133
+ }
134
+ exports.sanitizeConfig = sanitizeConfig;
135
+ /**
136
+ * Retrieves the configuration settings for UI5 flexibility services.
137
+ *
138
+ * @returns An array of flexibility service configurations, each specifying a connector
139
+ * and its options, such as the layers it applies to and its service URL, if applicable.
140
+ */
141
+ function getFlexSettings() {
142
+ const localConnectorPath = 'custom.connectors.WorkspaceConnector';
143
+ return [
144
+ { connector: 'LrepConnector', layers: [], url: '/sap/bc/lrep' },
145
+ {
146
+ applyConnector: localConnectorPath,
147
+ writeConnector: localConnectorPath,
148
+ custom: true
149
+ },
150
+ {
151
+ connector: 'LocalStorageConnector',
152
+ layers: ['CUSTOMER', 'USER']
153
+ }
154
+ ];
155
+ }
156
+ /**
157
+ * Add an application to the local FLP preview.
158
+ *
159
+ * @param templateConfig configuration for the preview
160
+ * @param manifest manifest of the additional target app
161
+ * @param app configuration for the preview
162
+ * @param logger logger instance
163
+ */
164
+ function addApp(templateConfig, manifest, app, logger) {
165
+ var _a, _b, _c, _d, _e, _f;
166
+ return __awaiter(this, void 0, void 0, function* () {
167
+ const id = manifest['sap.app'].id;
168
+ (_a = app.intent) !== null && _a !== void 0 ? _a : (app.intent = {
169
+ object: id.replace(/\./g, ''),
170
+ action: 'preview'
171
+ });
172
+ templateConfig.ui5.resources[id] = app.target;
173
+ templateConfig.apps[`${(_b = app.intent) === null || _b === void 0 ? void 0 : _b.object}-${(_c = app.intent) === null || _c === void 0 ? void 0 : _c.action}`] = {
174
+ title: (_d = (yield getI18nTextFromProperty(app.local, manifest['sap.app'].title, logger))) !== null && _d !== void 0 ? _d : id,
175
+ description: (_e = (yield getI18nTextFromProperty(app.local, manifest['sap.app'].description, logger))) !== null && _e !== void 0 ? _e : '',
176
+ additionalInformation: `SAPUI5.Component=${(_f = app.componentId) !== null && _f !== void 0 ? _f : id}`,
177
+ applicationType: 'URL',
178
+ url: app.target,
179
+ applicationDependencies: { manifest: true }
180
+ };
181
+ });
182
+ }
183
+ exports.addApp = addApp;
184
+ /**
185
+ * Get the i18n text of the given property.
186
+ *
187
+ * @param projectRoot absolute path to the project root
188
+ * @param propertyValue value of the property
189
+ * @param logger logger instance
190
+ * @returns i18n text of the property
191
+ */
192
+ function getI18nTextFromProperty(projectRoot, propertyValue, logger) {
193
+ var _a, _b, _c, _d;
194
+ return __awaiter(this, void 0, void 0, function* () {
195
+ //i18n model format could be {{key}} or {i18n>key}
196
+ if (!projectRoot || !propertyValue || propertyValue.search(/{{\w+}}|{i18n>\w+}/g) === -1) {
197
+ return propertyValue;
198
+ }
199
+ const propertyI18nKey = propertyValue.replace(/i18n>|[{}]/g, '');
200
+ const projectAccess = yield (0, project_access_1.createProjectAccess)(projectRoot);
201
+ try {
202
+ const bundle = (yield projectAccess.getApplication('').getI18nBundles())['sap.app'];
203
+ return (_d = (_c = (_b = (_a = bundle[propertyI18nKey]) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.value) === null || _c === void 0 ? void 0 : _c.value) !== null && _d !== void 0 ? _d : propertyI18nKey;
204
+ }
205
+ catch (e) {
206
+ logger.warn('Failed to load i18n properties bundle');
207
+ }
208
+ return propertyI18nKey;
209
+ });
210
+ }
211
+ /**
212
+ * Creates the configuration object for the sandbox.html template.
213
+ *
214
+ * @param config FLP configuration
215
+ * @param manifest application manifest
216
+ * @returns configuration object for the sandbox.html template
217
+ */
218
+ function createFlpTemplateConfig(config, manifest) {
219
+ var _a, _b, _c, _d;
220
+ const flex = getFlexSettings();
221
+ const supportedThemes = (_b = (_a = manifest['sap.ui5']) === null || _a === void 0 ? void 0 : _a.supportedThemes) !== null && _b !== void 0 ? _b : [exports.DEFAULT_THEME];
222
+ const ui5Theme = (_c = config.theme) !== null && _c !== void 0 ? _c : (supportedThemes.includes(exports.DEFAULT_THEME) ? exports.DEFAULT_THEME : supportedThemes[0]);
223
+ const id = manifest['sap.app'].id;
224
+ const ns = id.replace(/\./g, '/');
225
+ return {
226
+ basePath: (_d = path_1.posix.relative(path_1.posix.dirname(config.path), '/')) !== null && _d !== void 0 ? _d : '.',
227
+ apps: {},
228
+ init: config.init ? ns + config.init : undefined,
229
+ ui5: {
230
+ libs: getUI5Libs(manifest),
231
+ theme: ui5Theme,
232
+ flex,
233
+ resources: {
234
+ [exports.PREVIEW_URL.client.ns]: exports.PREVIEW_URL.client.url
235
+ },
236
+ bootstrapOptions: ''
237
+ },
238
+ locateReuseLibsScript: config.libs
239
+ };
240
+ }
241
+ exports.createFlpTemplateConfig = createFlpTemplateConfig;
242
+ /**
243
+ * Creates the configuration object for the test template.
244
+ *
245
+ * @param config test configuration
246
+ * @param id application id
247
+ * @returns configuration object for the test template
248
+ */
249
+ function createTestTemplateConfig(config, id) {
250
+ var _a;
251
+ return {
252
+ id,
253
+ framework: config.framework,
254
+ basePath: (_a = path_1.posix.relative(path_1.posix.dirname(config.path), '/')) !== null && _a !== void 0 ? _a : '.',
255
+ initPath: path_1.posix.relative(path_1.posix.dirname(config.path), config.init)
256
+ };
257
+ }
258
+ exports.createTestTemplateConfig = createTestTemplateConfig;
259
+ /**
260
+ * Returns the preview paths.
261
+ *
262
+ * @param config configuration from the ui5.yaml
263
+ * @param logger logger instance
264
+ * @returns an array of preview paths
265
+ */
266
+ function getPreviewPaths(config, logger = new logger_1.ToolsLogger()) {
267
+ var _a;
268
+ const urls = [];
269
+ // remove incorrect configurations
270
+ sanitizeConfig(config, logger);
271
+ // add flp preview url
272
+ const flpConfig = getFlpConfigWithDefaults(config.flp);
273
+ urls.push({ path: `${flpConfig.path}#${flpConfig.intent.object}-${flpConfig.intent.action}`, type: 'preview' });
274
+ // add editor urls
275
+ if ((_a = config.rta) === null || _a === void 0 ? void 0 : _a.editors) {
276
+ config.rta.editors.forEach((editor) => {
277
+ urls.push({ path: editor.path, type: 'editor' });
278
+ });
279
+ }
280
+ // add test urls if configured
281
+ if (config.test) {
282
+ config.test.forEach((test) => {
283
+ const testConfig = (0, test_1.mergeTestConfigDefaults)(test);
284
+ urls.push({ path: testConfig.path, type: 'test' });
285
+ });
286
+ }
287
+ return urls;
288
+ }
289
+ exports.getPreviewPaths = getPreviewPaths;
290
+ /**
291
+ * Generates the preview files.
292
+ *
293
+ * @param basePath path to the application root
294
+ * @param config configuration from the ui5.yaml
295
+ * @param fs file system editor
296
+ * @param logger logger instance
297
+ * @returns a mem-fs editor with the preview files
298
+ */
299
+ function generatePreviewFiles(basePath, config, fs, logger = new logger_1.ToolsLogger()) {
300
+ return __awaiter(this, void 0, void 0, function* () {
301
+ // remove incorrect configurations
302
+ sanitizeConfig(config, logger);
303
+ // create file system if not provided
304
+ if (!fs) {
305
+ fs = (0, mem_fs_editor_1.create)((0, mem_fs_1.create)());
306
+ }
307
+ const templatePath = (0, path_1.join)(__dirname, '../../templates');
308
+ const webappPath = yield (0, project_access_1.getWebappPath)(basePath, fs);
309
+ const manifest = (yield fs.readJSON((0, path_1.join)(webappPath, 'manifest.json')));
310
+ // generate FLP configuration
311
+ const flpConfig = getFlpConfigWithDefaults(config.flp);
312
+ const flpTemplate = (0, fs_1.readFileSync)((0, path_1.join)(templatePath, 'flp/sandbox.html'), 'utf-8');
313
+ const flpTemplConfig = createFlpTemplateConfig(flpConfig, manifest);
314
+ yield addApp(flpTemplConfig, manifest, {
315
+ target: flpTemplConfig.basePath,
316
+ local: '.',
317
+ intent: flpConfig.intent
318
+ }, logger);
319
+ fs.write((0, path_1.join)(webappPath, flpConfig.path), (0, ejs_1.render)(flpTemplate, flpTemplConfig));
320
+ // optional test files
321
+ if (config.test) {
322
+ for (const test of config.test) {
323
+ const testConfig = (0, test_1.mergeTestConfigDefaults)(test);
324
+ if (['QUnit', 'OPA5'].includes(test.framework)) {
325
+ const testTemlpate = (0, fs_1.readFileSync)((0, path_1.join)(templatePath, 'test/qunit.html'), 'utf-8');
326
+ const testTemplateConfig = createTestTemplateConfig(testConfig, manifest['sap.app'].id);
327
+ fs.write((0, path_1.join)(webappPath, testConfig.path), (0, ejs_1.render)(testTemlpate, testTemplateConfig));
328
+ }
329
+ else if (test.framework === 'Testsuite') {
330
+ const testTemlpate = (0, fs_1.readFileSync)((0, path_1.join)(templatePath, 'test/testsuite.qunit.html'), 'utf-8');
331
+ const testTemplateConfig = {
332
+ basePath: flpTemplConfig.basePath,
333
+ initPath: testConfig.init
334
+ };
335
+ fs.write((0, path_1.join)(webappPath, testConfig.path), (0, ejs_1.render)(testTemlpate, testTemplateConfig));
336
+ }
337
+ }
338
+ }
339
+ return fs;
340
+ });
341
+ }
342
+ exports.generatePreviewFiles = generatePreviewFiles;
343
+ //# sourceMappingURL=config.js.map
@@ -4,56 +4,16 @@ import type { Editor as MemFsEditor } from 'mem-fs-editor';
4
4
  import type { Router } from 'express';
5
5
  import type { Logger, ToolsLogger } from '@sap-ux/logger';
6
6
  import type { MiddlewareUtils } from '@ui5/server';
7
- import type { Manifest, UI5FlexLayer } from '@sap-ux/project-access';
7
+ import type { Manifest } from '@sap-ux/project-access';
8
8
  import { type AdpPreviewConfig, type CommonChangeProperties, type OperationType } from '@sap-ux/adp-tooling';
9
- import type { App, FlpConfig, MiddlewareConfig, RtaConfig, TestConfig } from '../types';
9
+ import type { FlpConfig, MiddlewareConfig, RtaConfig, TestConfig } from '../types';
10
+ import { type TemplateConfig } from './config';
10
11
  /**
11
12
  * Enhanced request handler that exposes a list of endpoints for the cds-plugin-ui5.
12
13
  */
13
14
  export type EnhancedRouter = Router & {
14
15
  getAppPages?: () => string[];
15
16
  };
16
- export interface CustomConnector {
17
- applyConnector: string;
18
- writeConnector: string;
19
- custom: boolean;
20
- }
21
- export interface FlexConnector {
22
- connector: string;
23
- layers: string[];
24
- url?: string;
25
- }
26
- /**
27
- * Internal structure used to fill the sandbox.html template
28
- */
29
- export interface TemplateConfig {
30
- basePath: string;
31
- apps: Record<string, {
32
- title: string;
33
- description: string;
34
- additionalInformation: string;
35
- applicationType: 'URL';
36
- url: string;
37
- applicationDependencies?: {
38
- manifest: boolean;
39
- };
40
- }>;
41
- ui5: {
42
- libs: string;
43
- theme: string;
44
- flex: (CustomConnector | FlexConnector)[];
45
- bootstrapOptions: string;
46
- resources: Record<string, string>;
47
- };
48
- init?: string;
49
- flex?: {
50
- [key: string]: unknown;
51
- layer: UI5FlexLayer;
52
- developerMode: boolean;
53
- pluginScript?: string;
54
- };
55
- locateReuseLibsScript?: boolean;
56
- }
57
17
  type OnChangeRequestHandler = (type: OperationType, change: CommonChangeProperties, fs: MemFsEditor, logger: Logger) => Promise<void>;
58
18
  /**
59
19
  * Class handling preview of a sandbox FLP.
@@ -119,13 +79,6 @@ export declare class FlpSandbox {
119
79
  * Add additional routes for apps also to be shown in the local FLP.
120
80
  */
121
81
  private addRoutesForAdditionalApps;
122
- /**
123
- * Retrieves the configuration settings for UI5 flexibility services.
124
- *
125
- * @returns An array of flexibility service configurations, each specifying a connector
126
- * and its options, such as the layers it applies to and its service URL, if applicable.
127
- */
128
- private getFlexSettings;
129
82
  /**
130
83
  * Create required routes for flex.
131
84
  */
@@ -155,29 +108,6 @@ export declare class FlpSandbox {
155
108
  * @param id application id from manifest
156
109
  */
157
110
  private addTestRoutes;
158
- /**
159
- * Add an application to the local FLP preview.
160
- *
161
- * @param manifest manifest of the additional target app
162
- * @param app configuration for the preview
163
- */
164
- addApp(manifest: Manifest, app: App): Promise<void>;
165
- /**
166
- * Get the i18n text of the given property.
167
- *
168
- * @param projectRoot absolute path to the project root
169
- * @param propertyValue value of the property
170
- * @returns i18n text of the property
171
- * @private
172
- */
173
- private getI18nTextFromProperty;
174
- /**
175
- * Gets the UI5 libs dependencies from manifest.json.
176
- *
177
- * @param manifest application manifest
178
- * @returns UI5 libs that should preloaded
179
- */
180
- private getUI5Libs;
181
111
  }
182
112
  /**
183
113
  * Initialize the preview for an adaptation project.
package/dist/base/flp.js CHANGED
@@ -17,10 +17,10 @@ const fs_1 = require("fs");
17
17
  const path_1 = require("path");
18
18
  const express_1 = require("express");
19
19
  const adp_tooling_1 = require("@sap-ux/adp-tooling");
20
- const project_access_1 = require("@sap-ux/project-access");
21
20
  const btp_utils_1 = require("@sap-ux/btp-utils");
22
21
  const flex_1 = require("./flex");
23
22
  const test_1 = require("./test");
23
+ const config_1 = require("./config");
24
24
  const DEVELOPER_MODE_CONFIG = new Map([
25
25
  // Run application in design time mode
26
26
  // Adds bindingString to BindingInfo objects. Required to create and read PropertyBinding changes
@@ -30,60 +30,7 @@ const DEVELOPER_MODE_CONFIG = new Map([
30
30
  // Make sure that XML preprocessing results are correctly invalidated
31
31
  ['xx-viewCache', 'false']
32
32
  ]);
33
- /**
34
- * SAPUI5 delivered namespaces from https://ui5.sap.com/#/api/sap
35
- */
36
- const UI5_LIBS = [
37
- 'sap.apf',
38
- 'sap.base',
39
- 'sap.chart',
40
- 'sap.collaboration',
41
- 'sap.f',
42
- 'sap.fe',
43
- 'sap.fileviewer',
44
- 'sap.gantt',
45
- 'sap.landvisz',
46
- 'sap.m',
47
- 'sap.ndc',
48
- 'sap.ovp',
49
- 'sap.rules',
50
- 'sap.suite',
51
- 'sap.tnt',
52
- 'sap.ui',
53
- 'sap.uiext',
54
- 'sap.ushell',
55
- 'sap.uxap',
56
- 'sap.viz',
57
- 'sap.webanalytics',
58
- 'sap.zen'
59
- ];
60
33
  const DEFAULT_LIVERELOAD_PORT = 35729;
61
- /**
62
- * Default theme
63
- */
64
- const DEFAULT_THEME = 'sap_horizon';
65
- /**
66
- * Default path for mounting the local FLP.
67
- */
68
- const DEFAULT_PATH = '/test/flp.html';
69
- /**
70
- * Default intent
71
- */
72
- const DEFAULT_INTENT = {
73
- object: 'app',
74
- action: 'preview'
75
- };
76
- /**
77
- * Static settings
78
- */
79
- const PREVIEW_URL = {
80
- client: {
81
- url: '/preview/client',
82
- local: (0, path_1.join)(__dirname, '../../dist/client'),
83
- ns: 'open.ux.preview.client'
84
- },
85
- api: '/preview/api'
86
- };
87
34
  /**
88
35
  * Class handling preview of a sandbox FLP.
89
36
  */
@@ -97,21 +44,10 @@ class FlpSandbox {
97
44
  * @param logger logger instance
98
45
  */
99
46
  constructor(config, project, utils, logger) {
100
- var _a, _b, _c, _d, _e, _f, _g, _h, _j;
101
47
  this.project = project;
102
48
  this.utils = utils;
103
49
  this.logger = logger;
104
- this.config = {
105
- path: (_b = (_a = config.flp) === null || _a === void 0 ? void 0 : _a.path) !== null && _b !== void 0 ? _b : DEFAULT_PATH,
106
- intent: (_d = (_c = config.flp) === null || _c === void 0 ? void 0 : _c.intent) !== null && _d !== void 0 ? _d : DEFAULT_INTENT,
107
- apps: (_f = (_e = config.flp) === null || _e === void 0 ? void 0 : _e.apps) !== null && _f !== void 0 ? _f : [],
108
- libs: (_g = config.flp) === null || _g === void 0 ? void 0 : _g.libs,
109
- theme: (_h = config.flp) === null || _h === void 0 ? void 0 : _h.theme,
110
- init: (_j = config.flp) === null || _j === void 0 ? void 0 : _j.init
111
- };
112
- if (!this.config.path.startsWith('/')) {
113
- this.config.path = `/${this.config.path}`;
114
- }
50
+ this.config = (0, config_1.getFlpConfigWithDefaults)(config.flp);
115
51
  this.test = config.test;
116
52
  this.rta = config.rta;
117
53
  logger.debug(`Config: ${JSON.stringify({ flp: this.config, rta: this.rta, test: this.test })}`);
@@ -133,37 +69,22 @@ class FlpSandbox {
133
69
  * @param resources optional additional resource mappings
134
70
  */
135
71
  init(manifest, componentId, resources = {}) {
136
- var _a, _b, _c, _d, _e, _f, _g;
137
- var _h;
72
+ var _a, _b, _c;
73
+ var _d, _e;
138
74
  return __awaiter(this, void 0, void 0, function* () {
139
75
  this.createFlexHandler();
140
- const flex = this.getFlexSettings();
141
- const supportedThemes = (_b = (_a = manifest['sap.ui5']) === null || _a === void 0 ? void 0 : _a.supportedThemes) !== null && _b !== void 0 ? _b : [DEFAULT_THEME];
142
- const ui5Theme = (_c = this.config.theme) !== null && _c !== void 0 ? _c : (supportedThemes.includes(DEFAULT_THEME) ? DEFAULT_THEME : supportedThemes[0]);
76
+ (_a = (_d = this.config).libs) !== null && _a !== void 0 ? _a : (_d.libs = yield this.hasLocateReuseLibsScript());
143
77
  const id = manifest['sap.app'].id;
144
- const ns = id.replace(/\./g, '/');
145
- this.templateConfig = {
146
- basePath: (_d = path_1.posix.relative(path_1.posix.dirname(this.config.path), '/')) !== null && _d !== void 0 ? _d : '.',
147
- apps: {},
148
- init: this.config.init ? ns + this.config.init : undefined,
149
- ui5: {
150
- libs: this.getUI5Libs(manifest),
151
- theme: ui5Theme,
152
- flex,
153
- resources: Object.assign(Object.assign({}, resources), { [PREVIEW_URL.client.ns]: PREVIEW_URL.client.url }),
154
- bootstrapOptions: ''
155
- },
156
- locateReuseLibsScript: (_e = this.config.libs) !== null && _e !== void 0 ? _e : (yield this.hasLocateReuseLibsScript())
157
- };
158
- yield this.addApp(manifest, {
78
+ this.templateConfig = (0, config_1.createFlpTemplateConfig)(this.config, manifest);
79
+ yield (0, config_1.addApp)(this.templateConfig, manifest, {
159
80
  componentId,
160
- target: (_f = resources[componentId !== null && componentId !== void 0 ? componentId : id]) !== null && _f !== void 0 ? _f : this.templateConfig.basePath,
81
+ target: (_b = resources[componentId !== null && componentId !== void 0 ? componentId : id]) !== null && _b !== void 0 ? _b : this.templateConfig.basePath,
161
82
  local: '.',
162
83
  intent: this.config.intent
163
- });
84
+ }, this.logger);
164
85
  this.addStandardRoutes();
165
86
  if (this.rta) {
166
- (_g = (_h = this.rta).options) !== null && _g !== void 0 ? _g : (_h.options = {});
87
+ (_c = (_e = this.rta).options) !== null && _c !== void 0 ? _c : (_e.options = {});
167
88
  this.rta.options.baseId = componentId !== null && componentId !== void 0 ? componentId : id;
168
89
  this.rta.options.appName = id;
169
90
  this.addEditorRoutes(this.rta);
@@ -255,7 +176,7 @@ class FlpSandbox {
255
176
  */
256
177
  addStandardRoutes() {
257
178
  // register static client sources
258
- this.router.use(PREVIEW_URL.client.url, (0, express_1.static)(PREVIEW_URL.client.local));
179
+ this.router.use(config_1.PREVIEW_URL.client.url, (0, express_1.static)(config_1.PREVIEW_URL.client.local));
259
180
  // add route for the sandbox.html
260
181
  this.router.get(this.config.path, ((_req, res, next) => __awaiter(this, void 0, void 0, function* () {
261
182
  // inform the user if a html file exists on the filesystem
@@ -304,7 +225,7 @@ class FlpSandbox {
304
225
  };
305
226
  }
306
227
  if (manifest) {
307
- yield this.addApp(manifest, app);
228
+ yield (0, config_1.addApp)(this.templateConfig, manifest, app, this.logger);
308
229
  this.logger.info(`Adding additional intent: ${(_a = app.intent) === null || _a === void 0 ? void 0 : _a.object}-${(_b = app.intent) === null || _b === void 0 ? void 0 : _b.action}`);
309
230
  }
310
231
  else {
@@ -313,33 +234,12 @@ class FlpSandbox {
313
234
  }
314
235
  });
315
236
  }
316
- /**
317
- * Retrieves the configuration settings for UI5 flexibility services.
318
- *
319
- * @returns An array of flexibility service configurations, each specifying a connector
320
- * and its options, such as the layers it applies to and its service URL, if applicable.
321
- */
322
- getFlexSettings() {
323
- const localConnectorPath = 'custom.connectors.WorkspaceConnector';
324
- return [
325
- { connector: 'LrepConnector', layers: [], url: '/sap/bc/lrep' },
326
- {
327
- applyConnector: localConnectorPath,
328
- writeConnector: localConnectorPath,
329
- custom: true
330
- },
331
- {
332
- connector: 'LocalStorageConnector',
333
- layers: ['CUSTOMER', 'USER']
334
- }
335
- ];
336
- }
337
237
  /**
338
238
  * Create required routes for flex.
339
239
  */
340
240
  createFlexHandler() {
341
241
  const fs = (0, mem_fs_editor_1.create)((0, mem_fs_1.create)());
342
- const api = `${PREVIEW_URL.api}/changes`;
242
+ const api = `${config_1.PREVIEW_URL.api}/changes`;
343
243
  this.router.use(api, (0, express_1.json)());
344
244
  this.router.get(api, ((_req, res) => __awaiter(this, void 0, void 0, function* () {
345
245
  const changes = yield (0, flex_1.readChanges)(this.project, this.logger);
@@ -473,7 +373,6 @@ class FlpSandbox {
473
373
  this.logger.debug(`Add route for ${config.path}`);
474
374
  // add route for the *.qunit.html
475
375
  this.router.get(config.path, ((_req, res, next) => __awaiter(this, void 0, void 0, function* () {
476
- var _a;
477
376
  this.logger.debug(`Serving test route: ${config.path}`);
478
377
  const file = yield this.project.byPath(config.path);
479
378
  if (file) {
@@ -481,12 +380,7 @@ class FlpSandbox {
481
380
  next();
482
381
  }
483
382
  else {
484
- const templateConfig = {
485
- id,
486
- framework: config.framework,
487
- basePath: (_a = path_1.posix.relative(path_1.posix.dirname(config.path), '/')) !== null && _a !== void 0 ? _a : '.',
488
- initPath: path_1.posix.relative(path_1.posix.dirname(config.path), config.init)
489
- };
383
+ const templateConfig = (0, config_1.createTestTemplateConfig)(config, id);
490
384
  const html = (0, ejs_1.render)(htmlTemplate, templateConfig);
491
385
  this.sendResponse(res, 'text/html', 200, html);
492
386
  }
@@ -513,80 +407,6 @@ class FlpSandbox {
513
407
  })));
514
408
  }
515
409
  }
516
- /**
517
- * Add an application to the local FLP preview.
518
- *
519
- * @param manifest manifest of the additional target app
520
- * @param app configuration for the preview
521
- */
522
- addApp(manifest, app) {
523
- var _a, _b, _c, _d, _e, _f;
524
- return __awaiter(this, void 0, void 0, function* () {
525
- const id = manifest['sap.app'].id;
526
- (_a = app.intent) !== null && _a !== void 0 ? _a : (app.intent = {
527
- object: id.replace(/\./g, ''),
528
- action: 'preview'
529
- });
530
- this.templateConfig.ui5.resources[id] = app.target;
531
- this.templateConfig.apps[`${(_b = app.intent) === null || _b === void 0 ? void 0 : _b.object}-${(_c = app.intent) === null || _c === void 0 ? void 0 : _c.action}`] = {
532
- title: (_d = (yield this.getI18nTextFromProperty(app.local, manifest['sap.app'].title))) !== null && _d !== void 0 ? _d : id,
533
- description: (_e = (yield this.getI18nTextFromProperty(app.local, manifest['sap.app'].description))) !== null && _e !== void 0 ? _e : '',
534
- additionalInformation: `SAPUI5.Component=${(_f = app.componentId) !== null && _f !== void 0 ? _f : id}`,
535
- applicationType: 'URL',
536
- url: app.target,
537
- applicationDependencies: { manifest: true }
538
- };
539
- });
540
- }
541
- /**
542
- * Get the i18n text of the given property.
543
- *
544
- * @param projectRoot absolute path to the project root
545
- * @param propertyValue value of the property
546
- * @returns i18n text of the property
547
- * @private
548
- */
549
- getI18nTextFromProperty(projectRoot, propertyValue) {
550
- var _a, _b, _c, _d;
551
- return __awaiter(this, void 0, void 0, function* () {
552
- //i18n model format could be {{key}} or {i18n>key}
553
- if (!projectRoot || !propertyValue || propertyValue.search(/{{\w+}}|{i18n>\w+}/g) === -1) {
554
- return propertyValue;
555
- }
556
- const propertyI18nKey = propertyValue.replace(/i18n>|[{}]/g, '');
557
- const projectAccess = yield (0, project_access_1.createProjectAccess)(projectRoot);
558
- try {
559
- const bundle = (yield projectAccess.getApplication('').getI18nBundles())['sap.app'];
560
- return (_d = (_c = (_b = (_a = bundle[propertyI18nKey]) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.value) === null || _c === void 0 ? void 0 : _c.value) !== null && _d !== void 0 ? _d : propertyI18nKey;
561
- }
562
- catch (e) {
563
- this.logger.warn('Failed to load i18n properties bundle');
564
- }
565
- return propertyI18nKey;
566
- });
567
- }
568
- /**
569
- * Gets the UI5 libs dependencies from manifest.json.
570
- *
571
- * @param manifest application manifest
572
- * @returns UI5 libs that should preloaded
573
- */
574
- getUI5Libs(manifest) {
575
- var _a, _b;
576
- if ((_b = (_a = manifest['sap.ui5']) === null || _a === void 0 ? void 0 : _a.dependencies) === null || _b === void 0 ? void 0 : _b.libs) {
577
- const libNames = Object.keys(manifest['sap.ui5'].dependencies.libs);
578
- return libNames
579
- .filter((key) => {
580
- return UI5_LIBS.some((substring) => {
581
- return key === substring || key.startsWith(substring + '.');
582
- });
583
- })
584
- .join(',');
585
- }
586
- else {
587
- return 'sap.m,sap.ui.core,sap.ushell';
588
- }
589
- }
590
410
  }
591
411
  exports.FlpSandbox = FlpSandbox;
592
412
  /**
@@ -1,2 +1,3 @@
1
1
  export { FlpSandbox, initAdp } from './flp';
2
+ export { generatePreviewFiles, getPreviewPaths } from './config';
2
3
  //# sourceMappingURL=index.d.ts.map
@@ -1,7 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.initAdp = exports.FlpSandbox = void 0;
3
+ exports.getPreviewPaths = exports.generatePreviewFiles = exports.initAdp = exports.FlpSandbox = void 0;
4
4
  var flp_1 = require("./flp");
5
5
  Object.defineProperty(exports, "FlpSandbox", { enumerable: true, get: function () { return flp_1.FlpSandbox; } });
6
6
  Object.defineProperty(exports, "initAdp", { enumerable: true, get: function () { return flp_1.initAdp; } });
7
+ var config_1 = require("./config");
8
+ Object.defineProperty(exports, "generatePreviewFiles", { enumerable: true, get: function () { return config_1.generatePreviewFiles; } });
9
+ Object.defineProperty(exports, "getPreviewPaths", { enumerable: true, get: function () { return config_1.getPreviewPaths; } });
7
10
  //# sourceMappingURL=index.js.map
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
1
  export * from './ui5/middleware';
2
- export { FlpSandbox, initAdp } from './base';
2
+ export { FlpSandbox, initAdp, generatePreviewFiles, getPreviewPaths } from './base';
3
3
  export { FlpConfig, RtaConfig, TestConfig, MiddlewareConfig } from './types';
4
4
  //# sourceMappingURL=index.d.ts.map
package/dist/index.js CHANGED
@@ -14,9 +14,11 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
- exports.initAdp = exports.FlpSandbox = void 0;
17
+ exports.getPreviewPaths = exports.generatePreviewFiles = exports.initAdp = exports.FlpSandbox = void 0;
18
18
  __exportStar(require("./ui5/middleware"), exports);
19
19
  var base_1 = require("./base");
20
20
  Object.defineProperty(exports, "FlpSandbox", { enumerable: true, get: function () { return base_1.FlpSandbox; } });
21
21
  Object.defineProperty(exports, "initAdp", { enumerable: true, get: function () { return base_1.initAdp; } });
22
+ Object.defineProperty(exports, "generatePreviewFiles", { enumerable: true, get: function () { return base_1.generatePreviewFiles; } });
23
+ Object.defineProperty(exports, "getPreviewPaths", { enumerable: true, get: function () { return base_1.getPreviewPaths; } });
22
24
  //# sourceMappingURL=index.js.map
@@ -3,7 +3,7 @@ import type { UI5FlexLayer } from '@sap-ux/project-access';
3
3
  /**
4
4
  * Intent object consisting of an object and an action.
5
5
  */
6
- interface Intent {
6
+ export interface Intent {
7
7
  object: string;
8
8
  action: string;
9
9
  }
@@ -11,23 +11,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  const logger_1 = require("@sap-ux/logger");
13
13
  const flp_1 = require("../base/flp");
14
- /**
15
- * The developer mode is only supported for adaptation projects, therefore, notify the user if it is wrongly configured and then disable it.
16
- *
17
- * @param config configurations from the ui5.yaml
18
- * @param logger logger instance
19
- */
20
- function sanitizeConfig(config, logger) {
21
- if (config.rta && config.adp === undefined) {
22
- config.rta.editors = config.rta.editors.filter((editor) => {
23
- if (editor.developerMode) {
24
- logger.error('developerMode is ONLY supported for SAP UI5 adaptation projects.');
25
- logger.warn(`developerMode for ${editor.path} disabled`);
26
- }
27
- return !editor.developerMode;
28
- });
29
- }
30
- }
14
+ const config_1 = require("../base/config");
31
15
  /**
32
16
  * Create the router that is to be exposed as UI5 middleware.
33
17
  *
@@ -44,7 +28,7 @@ function createRouter({ resources, options, middlewareUtil }, logger) {
44
28
  // setting defaults
45
29
  const config = (_a = options.configuration) !== null && _a !== void 0 ? _a : {};
46
30
  (_b = config.flp) !== null && _b !== void 0 ? _b : (config.flp = {});
47
- sanitizeConfig(config, logger);
31
+ (0, config_1.sanitizeConfig)(config, logger);
48
32
  // configure the FLP sandbox based on information from the manifest
49
33
  const flp = new flp_1.FlpSandbox(config, resources.rootProject, middlewareUtil, logger);
50
34
  if (config.adp) {
@@ -60,7 +44,7 @@ function createRouter({ resources, options, middlewareUtil }, logger) {
60
44
  }
61
45
  }
62
46
  // add exposed endpoints for cds-plugin-ui5
63
- flp.router.getAppPages = () => [`${flp.config.path}#${flp.config.intent.object}-${flp.config.intent.action}`];
47
+ flp.router.getAppPages = () => (0, config_1.getPreviewPaths)(config).map(({ path }) => path);
64
48
  return flp.router;
65
49
  });
66
50
  }
package/package.json CHANGED
@@ -9,7 +9,7 @@
9
9
  "bugs": {
10
10
  "url": "https://github.com/SAP/open-ux-tools/issues?q=is%3Aopen+is%3Aissue+label%3Abug+label%3Apreview-middleware"
11
11
  },
12
- "version": "0.13.73",
12
+ "version": "0.14.0",
13
13
  "license": "Apache-2.0",
14
14
  "author": "@SAP/ux-tools-team",
15
15
  "main": "dist/index.js",
@@ -25,11 +25,11 @@
25
25
  "ejs": "3.1.10",
26
26
  "mem-fs": "2.1.0",
27
27
  "mem-fs-editor": "9.4.0",
28
- "@sap-ux/btp-utils": "0.14.4",
29
- "@sap-ux/project-access": "1.22.3",
30
- "@sap-ux/adp-tooling": "0.11.6",
28
+ "@sap-ux/logger": "0.5.1",
29
+ "@sap-ux/adp-tooling": "0.11.7",
31
30
  "@sap-ux/control-property-editor-sources": "npm:@sap-ux/control-property-editor@0.4.23",
32
- "@sap-ux/logger": "0.5.1"
31
+ "@sap-ux/btp-utils": "0.14.4",
32
+ "@sap-ux/project-access": "1.22.3"
33
33
  },
34
34
  "devDependencies": {
35
35
  "@types/ejs": "3.1.2",
@@ -45,11 +45,11 @@
45
45
  "supertest": "6.3.3",
46
46
  "@sap-ux-private/playwright": "0.0.3",
47
47
  "dotenv": "16.3.1",
48
- "@sap-ux/axios-extension": "1.14.1",
48
+ "@sap-ux/axios-extension": "1.14.2",
49
49
  "@private/preview-middleware-client": "npm:@sap-ux-private/preview-middleware-client@0.9.16",
50
50
  "@sap-ux/store": "0.6.0",
51
- "@sap-ux/ui5-info": "0.5.0",
52
- "@sap-ux/i18n": "0.0.7"
51
+ "@sap-ux/i18n": "0.0.7",
52
+ "@sap-ux/ui5-info": "0.5.0"
53
53
  },
54
54
  "peerDependencies": {
55
55
  "express": "4"