@sap-ux/app-config-writer 0.6.4 → 0.6.6

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.
@@ -66,7 +66,7 @@ async function updatePackageJson(basePath, fs, yamlPath, logger) {
66
66
  const cliForPreview = await (0, utils_1.getCLIForPreview)(basePath, yamlPath ?? '', fs);
67
67
  const dependencyName = '@sap-ux/cards-editor-middleware';
68
68
  packageJson.scripts ??= {};
69
- packageJson.scripts['start-cards-generator'] = `${cliForPreview} --open '${cardGeneratorPath}${intent}'`;
69
+ packageJson.scripts['start-cards-generator'] = `${cliForPreview} --open "${cardGeneratorPath}${intent}"`;
70
70
  if (packageJson.devDependencies?.[dependencyName]) {
71
71
  delete packageJson.devDependencies[dependencyName];
72
72
  logger?.info(`Removed devDependency ${dependencyName} from package.json. It is no longer needed because this feature has been integrated into fiori-tools-preview / preview-middleware.`);
@@ -0,0 +1,95 @@
1
+ import type { FlpConfig, MiddlewareConfig as PreviewConfig } from '@sap-ux/preview-middleware';
2
+ import type { Editor } from 'mem-fs-editor';
3
+ export type Script = {
4
+ name: string;
5
+ value: string;
6
+ };
7
+ /**
8
+ * Reads the scripts from the package.json file.
9
+ * Scripts will be buffered in map 'scriptsFromPackageJson' to avoid multiple reads of the package.json file.
10
+ *
11
+ * @param fs - file system reference
12
+ * @param basePath - base path to be used for the conversion
13
+ * @returns the scripts from the package.json file
14
+ */
15
+ export declare function getScriptsFromPackageJson(fs: Editor, basePath: string): Map<string, string>;
16
+ /**
17
+ * Extracts the URL details from a given script.
18
+ *
19
+ * It extracts the used mount point for the preview and the used intent.
20
+ *
21
+ * @param script - the content of the script
22
+ * @returns the URL details
23
+ */
24
+ export declare function extractUrlDetails(script: string): {
25
+ path: string | undefined;
26
+ intent: FlpConfig['intent'] | undefined;
27
+ };
28
+ /**
29
+ * Check if the script/-name is valid for the conversion.
30
+ *
31
+ * The script:
32
+ * - must contain 'ui5 serve' or 'fiori run' command
33
+ * - must not be a test script
34
+ * - must not relate to 'webapp/index.html'.
35
+ *
36
+ * The script name:
37
+ * - must not be 'start-variants-management'
38
+ * - must not be 'start-control-property-editor'
39
+ * - must not be 'start-cards-generator'.
40
+ *
41
+ * @param script - the script from the package.json file
42
+ * @param convertTests - indicator if test suite and test runner should be included in the conversion (default: false)
43
+ * @returns indicator if the script is valid
44
+ */
45
+ export declare function isValidPreviewScript(script: Script, convertTests?: boolean): boolean;
46
+ /**
47
+ * Get the first valid preview script from package.json that uses the given yaml config.
48
+ *
49
+ * @param yamlConfigName - name of the yaml config to be used
50
+ * @param fs - mem-fs reference to be used for file access
51
+ * @param basePath - path to project root, where package.json is
52
+ * @returns the run script or undefined
53
+ */
54
+ export declare function getRunScriptForYamlConfig(yamlConfigName: string, fs: Editor, basePath: string): Script | undefined;
55
+ /**
56
+ * Extract the UI5 yaml configuration file name from the script.
57
+ *
58
+ * @param script - the content of the script from the package.json file
59
+ * @returns the UI5 yaml configuration file name or 'ui5.yaml' as default
60
+ */
61
+ export declare function extractYamlConfigFileName(script: string): string;
62
+ /**
63
+ * Check if the path is a test path.
64
+ * 1) path matches pattern '**.qunit.html'
65
+ * 2) path is being used as test configuration path in yaml configuration.
66
+ *
67
+ * @param script - the script content
68
+ * @param configuration - the preview configuration
69
+ * @returns indicator if the path is a test path
70
+ */
71
+ export declare function isTestPath(script: Script, configuration?: PreviewConfig): boolean;
72
+ /**
73
+ * Checks if the passed path is an FLP path.
74
+ *
75
+ * @param script - the script content
76
+ * @param configuration - the preview configuration
77
+ * @returns indicator if the path is an FLP path
78
+ */
79
+ export declare function isFlpPath(script: Script, configuration: PreviewConfig): boolean;
80
+ /**
81
+ * Extracts the test path of a given script name from the related ui5-test-runner script.
82
+ * The relation is defined as usage in another script that references the given script name directly or via max. one indirection.
83
+ *
84
+ * Example:
85
+ * - 'ui:test-server': 'ui5 serve --config ./ui5-deprecated-tools-preview-theme.yaml'
86
+ * - 'ui:test-runner': 'ui5-test-runner --port 8081 --url http://localhost:8080/test/testsuite.qunit.html --report-dir ./target/'
87
+ * - 'ui:test': 'start-server-and-test ui:test-server http://localhost:8080/ ui:test-runner'
88
+ *
89
+ * The test path for script 'ui:test-server' is 'http://localhost:8080/test/testsuite.qunit.html' from 'ui:test-runner' as they are connected via one indirection ('ui:test').
90
+ *
91
+ * @param scriptName - the name of the script from the package.json file
92
+ * @returns the related test path
93
+ */
94
+ export declare function getTestPathForUi5TestRunner(scriptName: string): string | undefined;
95
+ //# sourceMappingURL=package-json.d.ts.map
@@ -0,0 +1,200 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getScriptsFromPackageJson = getScriptsFromPackageJson;
4
+ exports.extractUrlDetails = extractUrlDetails;
5
+ exports.isValidPreviewScript = isValidPreviewScript;
6
+ exports.getRunScriptForYamlConfig = getRunScriptForYamlConfig;
7
+ exports.extractYamlConfigFileName = extractYamlConfigFileName;
8
+ exports.isTestPath = isTestPath;
9
+ exports.isFlpPath = isFlpPath;
10
+ exports.getTestPathForUi5TestRunner = getTestPathForUi5TestRunner;
11
+ const path_1 = require("path");
12
+ const project_access_1 = require("@sap-ux/project-access");
13
+ /**
14
+ * Map of scripts from the package.json file.
15
+ */
16
+ const scriptsFromPackageJson = new Map();
17
+ /**
18
+ * Reads the scripts from the package.json file.
19
+ * Scripts will be buffered in map 'scriptsFromPackageJson' to avoid multiple reads of the package.json file.
20
+ *
21
+ * @param fs - file system reference
22
+ * @param basePath - base path to be used for the conversion
23
+ * @returns the scripts from the package.json file
24
+ */
25
+ function getScriptsFromPackageJson(fs, basePath) {
26
+ const packageJsonPath = (0, path_1.join)(basePath, 'package.json');
27
+ const packageJson = fs.readJSON(packageJsonPath);
28
+ scriptsFromPackageJson.clear();
29
+ Object.entries(packageJson?.scripts ?? {}).forEach(([scriptName, scriptContent]) => {
30
+ scriptsFromPackageJson.set(scriptName, scriptContent ?? '');
31
+ });
32
+ return scriptsFromPackageJson;
33
+ }
34
+ /**
35
+ * Extracts the URL details from a given script.
36
+ *
37
+ * It extracts the used mount point for the preview and the used intent.
38
+ *
39
+ * @param script - the content of the script
40
+ * @returns the URL details
41
+ */
42
+ function extractUrlDetails(script) {
43
+ //extract the URL from the 'open' command of the script
44
+ let url = / (?:--open|-o|--o) (\S*)/.exec(script)?.[1] ?? undefined;
45
+ //delete double or single quotes from the URL
46
+ url = url?.replace(/['"]/g, '');
47
+ //extract the path from the URL
48
+ const path = /^[^?#]+\.html/.exec(url ?? '')?.[0] ?? undefined;
49
+ //extract the intent from the URL
50
+ const intent = /(?<=#)\w+-\w+/.exec(url ?? '')?.[0] ?? undefined;
51
+ return {
52
+ path,
53
+ intent: intent
54
+ ? {
55
+ object: intent?.split('-')[0],
56
+ action: intent?.split('-')[1]
57
+ }
58
+ : undefined
59
+ };
60
+ }
61
+ /**
62
+ * Check if the script/-name is valid for the conversion.
63
+ *
64
+ * The script:
65
+ * - must contain 'ui5 serve' or 'fiori run' command
66
+ * - must not be a test script
67
+ * - must not relate to 'webapp/index.html'.
68
+ *
69
+ * The script name:
70
+ * - must not be 'start-variants-management'
71
+ * - must not be 'start-control-property-editor'
72
+ * - must not be 'start-cards-generator'.
73
+ *
74
+ * @param script - the script from the package.json file
75
+ * @param convertTests - indicator if test suite and test runner should be included in the conversion (default: false)
76
+ * @returns indicator if the script is valid
77
+ */
78
+ function isValidPreviewScript(script, convertTests = false) {
79
+ const isValidScriptName = script.name != 'start-variants-management' &&
80
+ script.name != 'start-control-property-editor' &&
81
+ script.name != 'start-cards-generator';
82
+ //eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
83
+ const startsWebServer = !!(script.value.includes('ui5 serve') || script.value.includes('fiori run'));
84
+ const { path } = extractUrlDetails(script.value);
85
+ const opensTest = isTestPath(script ?? '');
86
+ const opensIndexHtml = path === 'index.html';
87
+ //tests are only relevant if the conversion of test runners is excluded
88
+ return isValidScriptName && startsWebServer && !opensIndexHtml && (convertTests ? true : !opensTest);
89
+ }
90
+ /**
91
+ * Get the first valid preview script from package.json that uses the given yaml config.
92
+ *
93
+ * @param yamlConfigName - name of the yaml config to be used
94
+ * @param fs - mem-fs reference to be used for file access
95
+ * @param basePath - path to project root, where package.json is
96
+ * @returns the run script or undefined
97
+ */
98
+ function getRunScriptForYamlConfig(yamlConfigName, fs, basePath) {
99
+ const packageJsonPath = (0, path_1.join)(basePath, 'package.json');
100
+ const packageJson = fs.readJSON(packageJsonPath);
101
+ if (!packageJson) {
102
+ return undefined;
103
+ }
104
+ for (const [scriptName, scriptValue] of getScriptsFromPackageJson(fs, basePath)) {
105
+ if (isValidPreviewScript({ name: scriptName, value: scriptValue }) &&
106
+ extractYamlConfigFileName(scriptValue) === yamlConfigName) {
107
+ return {
108
+ name: scriptName,
109
+ value: scriptValue
110
+ };
111
+ }
112
+ }
113
+ return undefined;
114
+ }
115
+ /**
116
+ * Extract the UI5 yaml configuration file name from the script.
117
+ *
118
+ * @param script - the content of the script from the package.json file
119
+ * @returns the UI5 yaml configuration file name or 'ui5.yaml' as default
120
+ */
121
+ function extractYamlConfigFileName(script) {
122
+ return / (?:--config|-c) (\S*)/.exec(script)?.[1] ?? project_access_1.FileName.Ui5Yaml;
123
+ }
124
+ /**
125
+ * Check if the path is a test path.
126
+ * 1) path matches pattern '**.qunit.html'
127
+ * 2) path is being used as test configuration path in yaml configuration.
128
+ *
129
+ * @param script - the script content
130
+ * @param configuration - the preview configuration
131
+ * @returns indicator if the path is a test path
132
+ */
133
+ function isTestPath(script, configuration) {
134
+ const { path } = extractUrlDetails(script.value);
135
+ if (!path) {
136
+ return !!getTestPathForUi5TestRunner(script.name);
137
+ }
138
+ if (path.includes('.qunit.html')) {
139
+ return true;
140
+ }
141
+ return configuration?.test?.some((testConfig) => testConfig.path === path) ?? false;
142
+ }
143
+ /**
144
+ * Checks if the passed path is an FLP path.
145
+ *
146
+ * @param script - the script content
147
+ * @param configuration - the preview configuration
148
+ * @returns indicator if the path is an FLP path
149
+ */
150
+ function isFlpPath(script, configuration) {
151
+ const { path } = extractUrlDetails(script.value);
152
+ if (!path) {
153
+ return false;
154
+ }
155
+ const isRtaEditorPath = configuration.rta?.editors?.some((editor) => editor.path === path) ?? //NOSONAR
156
+ configuration.editors?.rta?.endpoints?.some((editor) => editor.path === path) ??
157
+ false;
158
+ const isCardsGeneratorPath = configuration.editors?.cardGenerator?.path === path;
159
+ return !isRtaEditorPath && !isCardsGeneratorPath && !isTestPath(script, configuration);
160
+ }
161
+ /**
162
+ * Extracts the test path of a given script name from the related ui5-test-runner script.
163
+ * The relation is defined as usage in another script that references the given script name directly or via max. one indirection.
164
+ *
165
+ * Example:
166
+ * - 'ui:test-server': 'ui5 serve --config ./ui5-deprecated-tools-preview-theme.yaml'
167
+ * - 'ui:test-runner': 'ui5-test-runner --port 8081 --url http://localhost:8080/test/testsuite.qunit.html --report-dir ./target/'
168
+ * - 'ui:test': 'start-server-and-test ui:test-server http://localhost:8080/ ui:test-runner'
169
+ *
170
+ * The test path for script 'ui:test-server' is 'http://localhost:8080/test/testsuite.qunit.html' from 'ui:test-runner' as they are connected via one indirection ('ui:test').
171
+ *
172
+ * @param scriptName - the name of the script from the package.json file
173
+ * @returns the related test path
174
+ */
175
+ function getTestPathForUi5TestRunner(scriptName) {
176
+ const TEST_RUNNER_COMMAND = 'ui5-test-runner';
177
+ const extractUrl = (script) => {
178
+ return / (?:--url|-u|--testsuite) (\S*)/.exec(script)?.[1] ?? undefined;
179
+ };
180
+ const findReferencingScriptByScriptName = (scriptName) => {
181
+ return [...scriptsFromPackageJson.values()].find((tmpScriptValue) => tmpScriptValue.includes(` ${scriptName} `));
182
+ };
183
+ const findReferencingUi5TestRunnerScriptByScriptValue = (script) => {
184
+ for (const scriptPart of script.split(' ')) {
185
+ const scriptValue = scriptsFromPackageJson.get(scriptPart);
186
+ if (scriptValue?.includes(TEST_RUNNER_COMMAND)) {
187
+ return scriptValue;
188
+ }
189
+ }
190
+ return undefined;
191
+ };
192
+ let testRunnerScript = findReferencingScriptByScriptName(scriptName);
193
+ let url = testRunnerScript?.includes(TEST_RUNNER_COMMAND) ? extractUrl(testRunnerScript) : undefined;
194
+ if (!url) {
195
+ testRunnerScript = findReferencingUi5TestRunnerScriptByScriptValue(testRunnerScript ?? '');
196
+ url = extractUrl(testRunnerScript ?? '');
197
+ }
198
+ return url ? new URL(url).pathname : undefined;
199
+ }
200
+ //# sourceMappingURL=package-json.js.map
@@ -2,6 +2,12 @@ import type { Editor } from 'mem-fs-editor';
2
2
  import type { ToolsLogger } from '@sap-ux/logger';
3
3
  import type { PreviewConfigOptions } from '../types';
4
4
  import type { CustomMiddleware, FioriAppReloadConfig, UI5Config } from '@sap-ux/ui5-config';
5
+ import { type DefaultFlpPath, type MiddlewareConfig as PreviewConfig, type TestConfig } from '@sap-ux/preview-middleware';
6
+ import { type Script } from './package-json';
7
+ type ArrayElement<ArrayType extends readonly unknown[]> = ArrayType[number];
8
+ type PreviewTestConfig = ArrayElement<Required<PreviewConfig>['test']>;
9
+ export declare const DEFAULT_FLP_PATH: DefaultFlpPath;
10
+ export declare const TEST_CONFIG_DEFAULTS: Record<string, Readonly<Required<PreviewTestConfig>>>;
5
11
  /**
6
12
  * Gets the reload middleware form the provided yamlConfig.
7
13
  * The middleware can either be named 'fiori-tools-appreload' or 'reload-middleware'.
@@ -29,4 +35,53 @@ export declare function createPreviewMiddlewareConfig(fs: Editor, basePath: stri
29
35
  * @param logger - logger
30
36
  */
31
37
  export declare function updateMiddlewaresForPreview(fs: Editor, basePath: string, yamlPath?: string, logger?: ToolsLogger): Promise<void>;
38
+ /**
39
+ * Sanitizes the preview middleware configuration.
40
+ *
41
+ * In case the deprecated 'rta.editors' config is being used it is moves to 'editors.rta'.
42
+ * In case of an outdated preview configuration, the following changes will be applied:
43
+ * - property 'ui5Theme' will be moved to 'flp.theme'.
44
+ * - no longer used property 'component' will be removed.
45
+ *
46
+ * @param previewMiddleware - the preview middleware
47
+ * @returns the sanitized preview middleware
48
+ */
49
+ export declare function sanitizePreviewMiddleware(previewMiddleware: CustomMiddleware<PreviewConfigOptions>): CustomMiddleware<PreviewConfig | undefined>;
50
+ /**
51
+ * Creates a preview middleware configuration.
52
+ *
53
+ * It will sanitize the given preview middleware configuration and construct the flp configuration out of the given intent and path.
54
+ *
55
+ * @param previewMiddleware - the preview middleware configuration
56
+ * @param script - the content of the script from the package.json file
57
+ * @param basePath - the base path
58
+ * @param fs - file system reference
59
+ * @param logger logger to report info to the user
60
+ * @returns the preview middleware configuration
61
+ */
62
+ export declare function updatePreviewMiddlewareConfig(previewMiddleware: CustomMiddleware<PreviewConfigOptions>, script: Script, basePath: string, fs: Editor, logger?: ToolsLogger): Promise<CustomMiddleware<PreviewConfigOptions>>;
63
+ /**
64
+ * Update the test configuration.
65
+ *
66
+ * @param testConfiguration - the test configuration
67
+ * @param path - the path
68
+ * @param basePath - the base path
69
+ * @param fs - file system reference
70
+ * @param logger logger to report info to the user
71
+ * @returns the updated test configuration
72
+ */
73
+ export declare function updateTestConfig(testConfiguration: PreviewConfig['test'], path: string | undefined, basePath: string, fs: Editor, logger?: ToolsLogger): Promise<PreviewConfig['test']>;
74
+ /**
75
+ * Sanitize the test script (*.qunit.[jt]s)
76
+ * If the OPA5 test script uses the JourneyRunner, it will be renamed and added as pattern to the respective UI5 yaml configuration.
77
+ * If the test script does not use the JourneyRunner, it will be deleted.
78
+ *
79
+ * @param fs - file system reference
80
+ * @param basePath - base path to be used
81
+ * @param path - the path to the test runner html file
82
+ * @param newConfig - the new test configuration
83
+ * @param logger logger to report info to the user
84
+ */
85
+ export declare function sanitizeTestScript(fs: Editor, basePath: string, path: string, newConfig: TestConfig, logger?: ToolsLogger): Promise<void>;
86
+ export {};
32
87
  //# sourceMappingURL=ui5-yaml.d.ts.map
@@ -1,12 +1,38 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TEST_CONFIG_DEFAULTS = exports.DEFAULT_FLP_PATH = void 0;
3
4
  exports.getEnhancedReloadMiddleware = getEnhancedReloadMiddleware;
4
5
  exports.createPreviewMiddlewareConfig = createPreviewMiddlewareConfig;
5
6
  exports.updateMiddlewaresForPreview = updateMiddlewaresForPreview;
7
+ exports.sanitizePreviewMiddleware = sanitizePreviewMiddleware;
8
+ exports.updatePreviewMiddlewareConfig = updatePreviewMiddlewareConfig;
9
+ exports.updateTestConfig = updateTestConfig;
10
+ exports.sanitizeTestScript = sanitizeTestScript;
6
11
  const path_1 = require("path");
7
12
  const types_1 = require("../types");
8
13
  const project_access_1 = require("@sap-ux/project-access");
9
- const utils_1 = require("../common/utils");
14
+ const utils_1 = require("./utils");
15
+ const preview_middleware_1 = require("@sap-ux/preview-middleware");
16
+ const package_json_1 = require("./package-json");
17
+ const DEFAULT_INTENT = {
18
+ object: 'app',
19
+ action: 'preview'
20
+ };
21
+ exports.DEFAULT_FLP_PATH = '/test/flp.html';
22
+ exports.TEST_CONFIG_DEFAULTS = {
23
+ qunit: {
24
+ path: '/test/unitTests.qunit.html',
25
+ framework: 'QUnit'
26
+ },
27
+ opa5: {
28
+ path: '/test/opaTests.qunit.html',
29
+ framework: 'OPA5'
30
+ },
31
+ testsuite: {
32
+ path: '/test/testsuite.qunit.html',
33
+ framework: 'Testsuite'
34
+ }
35
+ };
10
36
  /**
11
37
  * Gets the reload middleware form the provided yamlConfig.
12
38
  * The middleware can either be named 'fiori-tools-appreload' or 'reload-middleware'.
@@ -56,11 +82,21 @@ async function updateMiddlewaresForPreview(fs, basePath, yamlPath, logger) {
56
82
  const ui5YamlFile = yamlPath ? (0, path_1.basename)(yamlPath) : project_access_1.FileName.Ui5Yaml;
57
83
  const ui5YamlConfig = await (0, project_access_1.readUi5Yaml)(basePath, ui5YamlFile, fs);
58
84
  let previewMiddleware = await (0, utils_1.getPreviewMiddleware)(ui5YamlConfig);
59
- const reloadMiddleware = await getEnhancedReloadMiddleware(ui5YamlConfig);
60
85
  if (!previewMiddleware) {
61
86
  logger?.warn(`No preview middleware found in ${ui5YamlFile}. Preview middleware will be added.`);
62
87
  previewMiddleware = createPreviewMiddlewareConfig(fs, basePath);
63
88
  }
89
+ else {
90
+ const script = (0, package_json_1.getRunScriptForYamlConfig)(ui5YamlFile, fs, basePath);
91
+ if (script) {
92
+ previewMiddleware = await updatePreviewMiddlewareConfig(previewMiddleware, script, basePath, fs, logger);
93
+ }
94
+ else {
95
+ //if we don't find a script for flp.path and intent we assume the default values and sanitize the config
96
+ previewMiddleware = sanitizePreviewMiddleware(previewMiddleware);
97
+ }
98
+ }
99
+ const reloadMiddleware = await getEnhancedReloadMiddleware(ui5YamlConfig);
64
100
  if (reloadMiddleware) {
65
101
  previewMiddleware.afterMiddleware = reloadMiddleware.name;
66
102
  ui5YamlConfig.updateCustomMiddleware(reloadMiddleware);
@@ -70,4 +106,172 @@ async function updateMiddlewaresForPreview(fs, basePath, yamlPath, logger) {
70
106
  fs.write((0, path_1.join)(basePath, ui5YamlFile), ui5YamlConfig.toString());
71
107
  logger?.debug(`Updated preview middleware in ${ui5YamlFile}.`);
72
108
  }
109
+ /**
110
+ * Sanitizes the preview middleware configuration.
111
+ *
112
+ * In case the deprecated 'rta.editors' config is being used it is moves to 'editors.rta'.
113
+ * In case of an outdated preview configuration, the following changes will be applied:
114
+ * - property 'ui5Theme' will be moved to 'flp.theme'.
115
+ * - no longer used property 'component' will be removed.
116
+ *
117
+ * @param previewMiddleware - the preview middleware
118
+ * @returns the sanitized preview middleware
119
+ */
120
+ function sanitizePreviewMiddleware(previewMiddleware) {
121
+ if (!previewMiddleware.configuration) {
122
+ return previewMiddleware;
123
+ }
124
+ //if we find the deprecated 'rta.editors' config, we will sanitize it
125
+ if ('rta' in previewMiddleware.configuration) {
126
+ const rtaConfig = (0, preview_middleware_1.sanitizeRtaConfig)(previewMiddleware.configuration.rta); //NOSONAR
127
+ delete previewMiddleware.configuration.rta; //NOSONAR
128
+ previewMiddleware.configuration.editors ??= {};
129
+ previewMiddleware.configuration.editors.rta = rtaConfig;
130
+ }
131
+ if (!(0, utils_1.isFioriToolsDeprecatedPreviewConfig)(previewMiddleware.configuration)) {
132
+ return previewMiddleware;
133
+ }
134
+ const ui5Theme = previewMiddleware.configuration.ui5Theme;
135
+ delete previewMiddleware.configuration;
136
+ if (!ui5Theme) {
137
+ return previewMiddleware;
138
+ }
139
+ const configuration = {};
140
+ configuration.flp = {};
141
+ configuration.flp.theme = ui5Theme;
142
+ previewMiddleware.configuration = configuration;
143
+ return previewMiddleware;
144
+ }
145
+ /**
146
+ * Creates a preview middleware configuration.
147
+ *
148
+ * It will sanitize the given preview middleware configuration and construct the flp configuration out of the given intent and path.
149
+ *
150
+ * @param previewMiddleware - the preview middleware configuration
151
+ * @param script - the content of the script from the package.json file
152
+ * @param basePath - the base path
153
+ * @param fs - file system reference
154
+ * @param logger logger to report info to the user
155
+ * @returns the preview middleware configuration
156
+ */
157
+ async function updatePreviewMiddlewareConfig(previewMiddleware, script, basePath, fs, logger) {
158
+ const { path, intent } = (0, package_json_1.extractUrlDetails)(script.value);
159
+ const defaultIntent = `${DEFAULT_INTENT.object}-${DEFAULT_INTENT.action}`;
160
+ const newMiddlewareConfig = sanitizePreviewMiddleware(previewMiddleware);
161
+ //copy of configuration to avoid ending up with an empty configuration object in some cases
162
+ const configuration = { ...newMiddlewareConfig.configuration };
163
+ let writeConfig = false;
164
+ if ((0, package_json_1.isFlpPath)(script, configuration)) {
165
+ //adjust path but respect defaults
166
+ if (!path?.includes(exports.DEFAULT_FLP_PATH)) {
167
+ configuration.flp = configuration.flp ?? {};
168
+ configuration.flp.path = path;
169
+ writeConfig = true;
170
+ }
171
+ //adjust intent but respect defaults
172
+ if (intent && `${intent?.object}-${intent?.action}` !== defaultIntent) {
173
+ configuration.flp = configuration.flp ?? {};
174
+ configuration.flp.intent = {
175
+ object: intent.object,
176
+ action: intent.action
177
+ };
178
+ writeConfig = true;
179
+ }
180
+ }
181
+ else if (path && (0, package_json_1.isTestPath)(script, configuration)) {
182
+ configuration.test = await updateTestConfig(configuration.test, path, basePath, fs, logger);
183
+ writeConfig = true;
184
+ }
185
+ else if (!path) {
186
+ const ui5TestRunnerPath = (0, package_json_1.getTestPathForUi5TestRunner)(script.name);
187
+ if (ui5TestRunnerPath) {
188
+ configuration.test = await updateTestConfig(configuration.test, ui5TestRunnerPath, basePath, fs);
189
+ writeConfig = true;
190
+ }
191
+ }
192
+ if (writeConfig) {
193
+ newMiddlewareConfig.configuration = configuration;
194
+ }
195
+ return newMiddlewareConfig;
196
+ }
197
+ /**
198
+ * Update the test configuration.
199
+ *
200
+ * @param testConfiguration - the test configuration
201
+ * @param path - the path
202
+ * @param basePath - the base path
203
+ * @param fs - file system reference
204
+ * @param logger logger to report info to the user
205
+ * @returns the updated test configuration
206
+ */
207
+ async function updateTestConfig(testConfiguration, path, basePath, fs, logger) {
208
+ const hasTestsuite = (config) => {
209
+ return config?.some((test) => test.framework === 'Testsuite') ?? false;
210
+ };
211
+ testConfiguration = testConfiguration ?? [];
212
+ let framework;
213
+ if (path?.includes('testsuite.qunit.html')) {
214
+ framework = 'Testsuite';
215
+ }
216
+ else if (path?.includes('opaTests.qunit.html')) {
217
+ framework = 'OPA5';
218
+ }
219
+ else if (path?.includes('unitTests.qunit.html')) {
220
+ framework = 'QUnit';
221
+ }
222
+ if (!framework) {
223
+ return testConfiguration;
224
+ }
225
+ const defaultPath = exports.TEST_CONFIG_DEFAULTS[framework.toLowerCase()].path;
226
+ const testConfig = testConfiguration.find((test) => test.framework === framework);
227
+ if (testConfig) {
228
+ testConfig.path = path;
229
+ if (testConfig.path === defaultPath) {
230
+ //sanitize default path
231
+ delete testConfig.path;
232
+ }
233
+ }
234
+ else {
235
+ const newConfig = {
236
+ framework,
237
+ ...(path && defaultPath !== (path.startsWith('/') ? path : `/${path}`) && { path })
238
+ };
239
+ await sanitizeTestScript(fs, basePath, path ?? defaultPath, newConfig, logger);
240
+ testConfiguration.push({ ...newConfig });
241
+ if (!hasTestsuite(testConfiguration)) {
242
+ testConfiguration.push({ framework: 'Testsuite' });
243
+ logger?.info(`The test framework 'Testsuite' has been added because at least one test runner has been found.`);
244
+ }
245
+ }
246
+ return testConfiguration;
247
+ }
248
+ /**
249
+ * Sanitize the test script (*.qunit.[jt]s)
250
+ * If the OPA5 test script uses the JourneyRunner, it will be renamed and added as pattern to the respective UI5 yaml configuration.
251
+ * If the test script does not use the JourneyRunner, it will be deleted.
252
+ *
253
+ * @param fs - file system reference
254
+ * @param basePath - base path to be used
255
+ * @param path - the path to the test runner html file
256
+ * @param newConfig - the new test configuration
257
+ * @param logger logger to report info to the user
258
+ */
259
+ async function sanitizeTestScript(fs, basePath, path, newConfig, logger) {
260
+ const jsTestScriptPath = (0, path_1.join)(await (0, project_access_1.getWebappPath)(basePath), path.replace('.html', '.js'));
261
+ const tsTestScriptPath = (0, path_1.join)(await (0, project_access_1.getWebappPath)(basePath), path.replace('.html', '.ts'));
262
+ const testScriptPath = fs.exists(jsTestScriptPath) ? jsTestScriptPath : tsTestScriptPath;
263
+ if (fs.exists(testScriptPath)) {
264
+ const file = fs.read(testScriptPath);
265
+ const usesJourneyRunner = file.includes('sap/fe/test/JourneyRunner');
266
+ if (usesJourneyRunner) {
267
+ const filePathRenamed = testScriptPath.replace(/(\.([jt])s)$/, '.custom$1');
268
+ fs.move(testScriptPath, filePathRenamed);
269
+ newConfig.pattern = `/test/**/${(0, path_1.basename)(filePathRenamed)}`;
270
+ logger?.info(`Renamed '${(0, path_1.basename)(testScriptPath)}' to '${(0, path_1.basename)(filePathRenamed)}'. This file creates the JourneyRunner for OPA5 tests. As the handling of journey runners is not part of the virtual OPA5 test runner endpoint, this file has been renamed and added to the respective UI5 YAML configuration.`);
271
+ }
272
+ else {
273
+ await (0, utils_1.deleteFiles)(fs, [testScriptPath]);
274
+ }
275
+ }
276
+ }
73
277
  //# sourceMappingURL=ui5-yaml.js.map
@@ -1,6 +1,7 @@
1
1
  import type { CustomMiddleware, UI5Config } from '@sap-ux/ui5-config';
2
2
  import type { PreviewConfigOptions, FioriToolsDeprecatedPreviewConfig } from '../types';
3
3
  import type { Editor } from 'mem-fs-editor';
4
+ import type { ToolsLogger } from '@sap-ux/logger';
4
5
  /**
5
6
  * Type guard to check if the given configuration is a deprecated preview middleware configuration.
6
7
  *
@@ -38,4 +39,12 @@ export declare function getIntentFromPreviewConfig(previewMiddlewareConfig: Prev
38
39
  * @returns - preview serve or undefined
39
40
  */
40
41
  export declare function getCLIForPreview(basePath: string, yamlFileName: string, fs: Editor): Promise<string | undefined>;
42
+ /**
43
+ * Deletes the given file.
44
+ *
45
+ * @param fs - file system reference
46
+ * @param files - files to be deleted
47
+ * @param logger logger to report info to the user
48
+ */
49
+ export declare function deleteFiles(fs: Editor, files: string[], logger?: ToolsLogger): Promise<void>;
41
50
  //# sourceMappingURL=utils.d.ts.map
@@ -4,8 +4,10 @@ exports.isFioriToolsDeprecatedPreviewConfig = isFioriToolsDeprecatedPreviewConfi
4
4
  exports.getPreviewMiddleware = getPreviewMiddleware;
5
5
  exports.getIntentFromPreviewConfig = getIntentFromPreviewConfig;
6
6
  exports.getCLIForPreview = getCLIForPreview;
7
+ exports.deleteFiles = deleteFiles;
7
8
  const project_access_1 = require("@sap-ux/project-access");
8
9
  const types_1 = require("../types");
10
+ const path_1 = require("path");
9
11
  /**
10
12
  * Type guard to check if the given configuration is a deprecated preview middleware configuration.
11
13
  *
@@ -61,4 +63,19 @@ async function getCLIForPreview(basePath, yamlFileName, fs) {
61
63
  const previewMiddleware = await getPreviewMiddleware(undefined, basePath, yamlFileName, fs);
62
64
  return previewMiddleware?.name === types_1.MiddlewareConfigs.PreviewMiddleware ? 'ui5 serve' : 'fiori run';
63
65
  }
66
+ /**
67
+ * Deletes the given file.
68
+ *
69
+ * @param fs - file system reference
70
+ * @param files - files to be deleted
71
+ * @param logger logger to report info to the user
72
+ */
73
+ async function deleteFiles(fs, files, logger) {
74
+ files.forEach((path) => {
75
+ if (fs.exists(path)) {
76
+ fs.delete(path);
77
+ logger?.info(`Deleted the '${(0, path_1.basename)(path)}' file. This file is no longer needed for the virtual endpoints.`);
78
+ }
79
+ });
80
+ }
64
81
  //# sourceMappingURL=utils.js.map