@sap-ux/preview-middleware 0.16.86 → 0.16.88

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.
@@ -2,6 +2,7 @@ import { ToolsLogger, type Logger } from '@sap-ux/logger';
2
2
  import type { App, FlpConfig, Intent, InternalTestConfig, MiddlewareConfig } from '../types';
3
3
  import { type Manifest, type UI5FlexLayer } from '@sap-ux/project-access';
4
4
  import { type Editor } from 'mem-fs-editor';
5
+ import type { MergedAppDescriptor } from '@sap-ux/axios-extension';
5
6
  export interface CustomConnector {
6
7
  applyConnector: string;
7
8
  writeConnector: string;
@@ -23,9 +24,7 @@ export interface TemplateConfig {
23
24
  additionalInformation: string;
24
25
  applicationType: 'URL';
25
26
  url: string;
26
- applicationDependencies?: {
27
- manifest: boolean;
28
- };
27
+ applicationDependencies?: MergedAppDescriptor;
29
28
  }>;
30
29
  ui5: {
31
30
  libs: string;
@@ -41,6 +40,10 @@ export interface TemplateConfig {
41
40
  developerMode: boolean;
42
41
  pluginScript?: string;
43
42
  };
43
+ features?: {
44
+ feature: string;
45
+ isEnabled: boolean;
46
+ }[];
44
47
  locateReuseLibsScript?: boolean;
45
48
  }
46
49
  /**
@@ -95,8 +98,9 @@ export declare function sanitizeConfig(config: MiddlewareConfig, logger: ToolsLo
95
98
  * @param manifest manifest of the additional target app
96
99
  * @param app configuration for the preview
97
100
  * @param logger logger instance
101
+ * @param descriptor descriptor of the additional target app
98
102
  */
99
- export declare function addApp(templateConfig: TemplateConfig, manifest: Partial<Manifest>, app: App, logger: Logger): Promise<void>;
103
+ export declare function addApp(templateConfig: TemplateConfig, manifest: Partial<Manifest>, app: App, logger: Logger, descriptor?: MergedAppDescriptor): Promise<void>;
100
104
  /**
101
105
  * Creates the configuration object for the sandbox.html template.
102
106
  *
@@ -156,22 +156,26 @@ function getFlexSettings() {
156
156
  * @param manifest manifest of the additional target app
157
157
  * @param app configuration for the preview
158
158
  * @param logger logger instance
159
+ * @param descriptor descriptor of the additional target app
159
160
  */
160
- async function addApp(templateConfig, manifest, app, logger) {
161
+ async function addApp(templateConfig, manifest, app, logger, descriptor) {
161
162
  const id = manifest['sap.app']?.id ?? '';
162
163
  app.intent ??= {
163
164
  object: id.replace(/\./g, ''),
164
165
  action: 'preview'
165
166
  };
167
+ const appName = `${app.intent?.object}-${app.intent?.action}`;
166
168
  templateConfig.ui5.resources[id] = app.target;
167
- templateConfig.apps[`${app.intent?.object}-${app.intent?.action}`] = {
169
+ templateConfig.apps[appName] = {
168
170
  title: (await getI18nTextFromProperty(app.local, manifest['sap.app']?.title, logger)) ?? id,
169
171
  description: (await getI18nTextFromProperty(app.local, manifest['sap.app']?.description, logger)) ?? '',
170
172
  additionalInformation: `SAPUI5.Component=${app.componentId ?? id}`,
171
173
  applicationType: 'URL',
172
- url: app.target,
173
- applicationDependencies: { manifest: true }
174
+ url: app.target
174
175
  };
176
+ if (descriptor) {
177
+ templateConfig.apps[appName].applicationDependencies = descriptor;
178
+ }
175
179
  }
176
180
  /**
177
181
  * Get the i18n text of the given property.
@@ -5,6 +5,7 @@ import type { Logger, ToolsLogger } from '@sap-ux/logger';
5
5
  import type { MiddlewareUtils } from '@ui5/server';
6
6
  import type { Manifest } from '@sap-ux/project-access';
7
7
  import { type AdpPreviewConfig, type CommonChangeProperties, type OperationType } from '@sap-ux/adp-tooling';
8
+ import type { MergedAppDescriptor } from '@sap-ux/axios-extension';
8
9
  import type { FlpConfig, MiddlewareConfig, RtaConfig, TestConfig } from '../types';
9
10
  import { type TemplateConfig } from './config';
10
11
  /**
@@ -48,8 +49,9 @@ export declare class FlpSandbox {
48
49
  * @param manifest application manifest
49
50
  * @param componentId optional componentId e.g. for adaptation projects
50
51
  * @param resources optional additional resource mappings
52
+ * @param descriptor optional additional descriptor mappings
51
53
  */
52
- init(manifest: Manifest, componentId?: string, resources?: Record<string, string>): Promise<void>;
54
+ init(manifest: Manifest, componentId?: string, resources?: Record<string, string>, descriptor?: MergedAppDescriptor): Promise<void>;
53
55
  /**
54
56
  * Generates the FLP sandbox for an editor.
55
57
  *
package/dist/base/flp.js CHANGED
@@ -10,6 +10,7 @@ const path_1 = require("path");
10
10
  const express_1 = require("express");
11
11
  const adp_tooling_1 = require("@sap-ux/adp-tooling");
12
12
  const btp_utils_1 = require("@sap-ux/btp-utils");
13
+ const feature_toggle_1 = require("@sap-ux/feature-toggle");
13
14
  const flex_1 = require("./flex");
14
15
  const test_1 = require("./test");
15
16
  const config_1 = require("./config");
@@ -68,8 +69,9 @@ class FlpSandbox {
68
69
  * @param manifest application manifest
69
70
  * @param componentId optional componentId e.g. for adaptation projects
70
71
  * @param resources optional additional resource mappings
72
+ * @param descriptor optional additional descriptor mappings
71
73
  */
72
- async init(manifest, componentId, resources = {}) {
74
+ async init(manifest, componentId, resources = {}, descriptor) {
73
75
  this.createFlexHandler();
74
76
  this.config.libs ??= await this.hasLocateReuseLibsScript();
75
77
  const id = manifest['sap.app'].id;
@@ -79,7 +81,7 @@ class FlpSandbox {
79
81
  target: resources[componentId ?? id] ?? this.templateConfig.basePath,
80
82
  local: '.',
81
83
  intent: this.config.intent
82
- }, this.logger);
84
+ }, this.logger, descriptor);
83
85
  this.addStandardRoutes();
84
86
  if (this.rta) {
85
87
  this.rta.options ??= {};
@@ -120,6 +122,7 @@ class FlpSandbox {
120
122
  developerMode: editor.developerMode === true,
121
123
  pluginScript: editor.pluginScript
122
124
  };
125
+ config.features = feature_toggle_1.FeatureToggleAccess.getAllFeatureToggles();
123
126
  if (editor.developerMode === true) {
124
127
  config.ui5.bootstrapOptions = serializeUi5Configuration(DEVELOPER_MODE_CONFIG);
125
128
  }
@@ -145,6 +148,7 @@ class FlpSandbox {
145
148
  templatePreviewUrl = templatePreviewUrl.replace('?', `?sap-ui-layer=${rta.layer}&`);
146
149
  }
147
150
  const template = (0, fs_1.readFileSync)((0, path_1.join)(__dirname, '../../templates/flp/editor.html'), 'utf-8');
151
+ const features = feature_toggle_1.FeatureToggleAccess.getAllFeatureToggles();
148
152
  const envPort = process.env.FIORI_TOOLS_LIVERELOAD_PORT;
149
153
  let livereloadPort = envPort ? parseInt(envPort, 10) : DEFAULT_LIVERELOAD_PORT;
150
154
  livereloadPort = isNaN(livereloadPort) ? DEFAULT_LIVERELOAD_PORT : livereloadPort;
@@ -155,7 +159,8 @@ class FlpSandbox {
155
159
  appName: rta.options?.appName,
156
160
  scenario,
157
161
  livereloadPort,
158
- livereloadUrl: envLivereloadUrl
162
+ livereloadUrl: envLivereloadUrl,
163
+ features: JSON.stringify(features)
159
164
  });
160
165
  this.sendResponse(res, 'text/html', 200, html);
161
166
  });
@@ -455,9 +460,8 @@ async function initAdp(rootProject, config, flp, util, logger) {
455
460
  }
456
461
  }
457
462
  const descriptor = adp.descriptor;
458
- descriptor.asyncHints.requests = [];
459
463
  const { name, manifest } = descriptor;
460
- await flp.init(manifest, name, adp.resources);
464
+ await flp.init(manifest, name, adp.resources, descriptor);
461
465
  flp.router.use(adp.descriptor.url, adp.proxy.bind(adp));
462
466
  flp.addOnChangeRequestHandler(adp.onChangeRequest.bind(adp));
463
467
  flp.router.use((0, express_1.json)());
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
 
3
- sap.ui.define([], function () {
3
+ sap.ui.define(["../../cpe/feature-service"], function (____cpe_feature_service) {
4
4
  "use strict";
5
5
 
6
6
  function __ui5_require_async(path) {
@@ -20,15 +20,15 @@ sap.ui.define([], function () {
20
20
  });
21
21
  });
22
22
  }
23
+ const FeatureService = ____cpe_feature_service["FeatureService"];
23
24
  /**
24
25
  * Loads the appropriate Quick Action registries for the given application type.
25
- *
26
- * @param appType - Application type.
26
+ *
27
+ * @param appType - Application type.
27
28
  * @returns Quick Action registries.
28
29
  */
29
30
  async function loadDefinitions(appType) {
30
- // eslint-disable-next-line fiori-custom/sap-no-localstorage
31
- if (localStorage.getItem('com.sap.ux.control-property-editor.features.quick-actions') !== 'true') {
31
+ if (FeatureService.isFeatureEnabled('cpe.beta.quick-actions') === false) {
32
32
  return [];
33
33
  }
34
34
  if (appType === 'fe-v2') {
@@ -1,15 +1,15 @@
1
+ import { FeatureService } from '../../cpe/feature-service';
1
2
  import type { QuickActionDefinitionRegistry } from '../../cpe/quick-actions/registry';
2
3
  import type { ApplicationType } from '../../utils/application';
3
4
 
4
5
  /**
5
6
  * Loads the appropriate Quick Action registries for the given application type.
6
- *
7
- * @param appType - Application type.
7
+ *
8
+ * @param appType - Application type.
8
9
  * @returns Quick Action registries.
9
10
  */
10
11
  export async function loadDefinitions(appType: ApplicationType): Promise<QuickActionDefinitionRegistry<string>[]> {
11
- // eslint-disable-next-line fiori-custom/sap-no-localstorage
12
- if (localStorage.getItem('com.sap.ux.control-property-editor.features.quick-actions') !== 'true') {
12
+ if (FeatureService.isFeatureEnabled('cpe.beta.quick-actions') === false) {
13
13
  return [];
14
14
  }
15
15
  if (appType === 'fe-v2') {
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+
3
+ sap.ui.define([], function () {
4
+ "use strict";
5
+
6
+ class FeatureService {
7
+ static features = {};
8
+ static #_ = (() => {
9
+ // eslint-disable-next-line fiori-custom/sap-no-dom-access, fiori-custom/sap-browser-api-warning
10
+ const bootstrapConfig = document.getElementById('sap-ui-bootstrap');
11
+ const features = bootstrapConfig?.getAttribute('data-open-ux-preview-features');
12
+ if (features) {
13
+ const featureToggles = JSON.parse(features);
14
+ for (const {
15
+ feature,
16
+ isEnabled
17
+ } of featureToggles) {
18
+ this.features[feature] = isEnabled;
19
+ }
20
+ }
21
+ })();
22
+ /**
23
+ * Checks if given feature is enabled.
24
+ *
25
+ * @param featureId - Id of the feature.
26
+ * @returns true if feature is enabled.
27
+ */
28
+ static isFeatureEnabled(featureId) {
29
+ return this.features[featureId] ?? false;
30
+ }
31
+ }
32
+ var __exports = {
33
+ __esModule: true
34
+ };
35
+ __exports.FeatureService = FeatureService;
36
+ return __exports;
37
+ });
38
+ //# sourceMappingURL=feature-service.js.map
@@ -0,0 +1,25 @@
1
+ export class FeatureService {
2
+ private static features: Record<string, boolean> = {};
3
+
4
+ static {
5
+ // eslint-disable-next-line fiori-custom/sap-no-dom-access, fiori-custom/sap-browser-api-warning
6
+ const bootstrapConfig = document.getElementById('sap-ui-bootstrap');
7
+ const features = bootstrapConfig?.getAttribute('data-open-ux-preview-features');
8
+ if (features) {
9
+ const featureToggles = JSON.parse(features) as { feature: string; isEnabled: boolean }[];
10
+ for (const { feature, isEnabled } of featureToggles) {
11
+ this.features[feature] = isEnabled;
12
+ }
13
+ }
14
+ }
15
+
16
+ /**
17
+ * Checks if given feature is enabled.
18
+ *
19
+ * @param featureId - Id of the feature.
20
+ * @returns true if feature is enabled.
21
+ */
22
+ public static isFeatureEnabled(featureId: string): boolean {
23
+ return this.features[featureId] ?? false;
24
+ }
25
+ }
@@ -15,10 +15,16 @@ async function ushellBootstrap(fnCallback) {
15
15
  const response = await fetch(`${basePath}/resources/sap-ui-version.json`);
16
16
  const json = await response.json();
17
17
  const version = json?.libraries?.find((lib) => lib.name === 'sap.ui.core')?.version ?? '1.121.0';
18
- const majorUi5Version = parseInt(version.split('.')[0], 10);
18
+ const [major, minor] = version.split('.');
19
+ const majorUi5Version = parseInt(major, 10);
20
+ const minorUi5Version = parseInt(minor, 10);
19
21
  if (majorUi5Version >= 2) {
20
22
  src = `${basePath}/resources/sap/ushell/bootstrap/sandbox2.js`;
21
23
  }
24
+
25
+ if (majorUi5Version === 1 && minorUi5Version < 72) {
26
+ removeAsyncHintsRequests();
27
+ }
22
28
  } catch (error) {
23
29
  console.warn('Failed to fetch sap-ui-version.json. Assuming it is a 1.x version.');
24
30
  }
@@ -33,6 +39,38 @@ async function ushellBootstrap(fnCallback) {
33
39
  }
34
40
  }
35
41
 
42
+ /**
43
+ * For UI5 version 1.71 and below, we need to remove the asyncHints.requests
44
+ * to load the changes in an Adaptation project.
45
+ * This logic needs to be executed here to have a reliable check for
46
+ * UI5 version and remove the asyncHints.requests before the sandbox is loaded.
47
+ * The sandbox shell modifies the `window['sap-ushell-config']`.
48
+ */
49
+ function removeAsyncHintsRequests() {
50
+ const obj = window['sap-ushell-config']['applications'];
51
+
52
+ if (!obj || typeof obj !== 'object') return;
53
+
54
+ const stack = [obj];
55
+
56
+ while (stack.length > 0) {
57
+ const current = stack.pop();
58
+
59
+ if (current.asyncHints) {
60
+ if (current.asyncHints.requests) {
61
+ current.asyncHints.requests = [];
62
+ }
63
+ return;
64
+ }
65
+
66
+ for (const key in current) {
67
+ if (typeof current[key] === 'object' && current[key] !== null) {
68
+ stack.push(current[key]);
69
+ }
70
+ }
71
+ }
72
+ }
73
+
36
74
  // eslint-disable-next-line fiori-custom/sap-no-global-define
37
75
  window['sap-ui-config'] = {
38
76
  'xx-bootTask': ushellBootstrap
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.16.86",
12
+ "version": "0.16.88",
13
13
  "license": "Apache-2.0",
14
14
  "author": "@SAP/ux-tools-team",
15
15
  "main": "dist/index.js",
@@ -27,8 +27,9 @@
27
27
  "mem-fs-editor": "9.4.0",
28
28
  "@sap-ux/logger": "0.6.0",
29
29
  "@sap-ux/btp-utils": "0.15.2",
30
- "@sap-ux/adp-tooling": "0.12.59",
31
- "@sap-ux/control-property-editor-sources": "npm:@sap-ux/control-property-editor@0.5.18",
30
+ "@sap-ux/feature-toggle": "0.2.2",
31
+ "@sap-ux/adp-tooling": "0.12.60",
32
+ "@sap-ux/control-property-editor-sources": "npm:@sap-ux/control-property-editor@0.5.20",
32
33
  "@sap-ux/project-access": "1.28.2"
33
34
  },
34
35
  "devDependencies": {
@@ -45,9 +46,9 @@
45
46
  "supertest": "6.3.3",
46
47
  "@sap-ux-private/playwright": "0.1.0",
47
48
  "dotenv": "16.3.1",
48
- "@private/preview-middleware-client": "npm:@sap-ux-private/preview-middleware-client@0.11.14",
49
- "@sap-ux/axios-extension": "1.16.6",
49
+ "@private/preview-middleware-client": "npm:@sap-ux-private/preview-middleware-client@0.11.16",
50
50
  "@sap-ux/store": "0.9.2",
51
+ "@sap-ux/axios-extension": "1.16.7",
51
52
  "@sap-ux/ui5-info": "0.8.1",
52
53
  "@sap-ux/i18n": "0.2.0"
53
54
  },
@@ -20,6 +20,7 @@
20
20
  scenario: '<%- scenario %>',
21
21
  livereloadPort: <%- livereloadPort %>,
22
22
  livereloadUrl: '<%- livereloadUrl %>',
23
+ features: <%- features %>
23
24
  });
24
25
  </script>
25
26
  </body>
@@ -62,6 +62,7 @@
62
62
  data-sap-ui-xx-componentPreload="off"<%- ui5.bootstrapOptions %>
63
63
  data-sap-ui-oninit="module:open/ux/preview/client/flp/init"<% if (locals.init) { %>
64
64
  data-open-ux-preview-customInit='<%- init %>'<% } if (locals.flex) { %>
65
+ data-open-ux-preview-features='<%- JSON.stringify(features) %>'
65
66
  data-open-ux-preview-flex-settings='<%- JSON.stringify(flex) %>'<% } if (locals.locateReuseLibsScript) { %>
66
67
  data-open-ux-preview-libs-manifests='<%- JSON.stringify(Object.values(apps).map(app => app.url)) %>'<% } %>>
67
68
  </script>