@sap-ux/fiori-migration-writer 0.0.4 → 0.0.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.
- package/dist/ProjectMigrator.d.ts +20 -8
- package/dist/ProjectMigrator.js +121 -123
- package/dist/adapters/ui5-config-adapter.js +64 -18
- package/dist/adapters/ui5-config-helpers.js +3 -10
- package/dist/components/extension.d.ts +3 -1
- package/dist/components/extension.js +5 -4
- package/dist/config/backend-i18n.d.ts +27 -6
- package/dist/config/backend-i18n.js +5 -11
- package/dist/config/flp/intent.d.ts +6 -3
- package/dist/config/flp/intent.js +6 -4
- package/dist/config/flp/sandbox.d.ts +3 -1
- package/dist/config/flp/sandbox.js +17 -12
- package/dist/config/launch-config.d.ts +4 -3
- package/dist/config/launch-config.js +5 -16
- package/dist/config/manifest-update.d.ts +21 -1
- package/dist/config/manifest-update.js +7 -12
- package/dist/config/package-json.d.ts +3 -1
- package/dist/config/package-json.js +15 -9
- package/dist/config/ui5-yaml.d.ts +9 -4
- package/dist/config/ui5-yaml.js +14 -10
- package/dist/data/sap-libraries.d.ts +3 -1
- package/dist/data/sap-libraries.js +4 -3
- package/dist/data/ui5-version.js +1 -1
- package/dist/files/project-files.d.ts +4 -3
- package/dist/files/project-files.js +10 -16
- package/dist/files/webapp.d.ts +5 -2
- package/dist/files/webapp.js +30 -35
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/migration-process/configuration.d.ts +3 -1
- package/dist/migration-process/configuration.js +3 -2
- package/dist/migration-process/legacy-helpers.d.ts +3 -1
- package/dist/migration-process/legacy-helpers.js +19 -32
- package/dist/migration-process/legacy.d.ts +3 -1
- package/dist/migration-process/legacy.js +66 -79
- package/dist/migration-process/migration-phases.d.ts +6 -1
- package/dist/migration-process/migration-phases.js +26 -14
- package/dist/migration-process/setup.d.ts +9 -6
- package/dist/migration-process/setup.js +19 -10
- package/dist/migration-process/validation.d.ts +5 -2
- package/dist/migration-process/validation.js +6 -4
- package/dist/migration-types.d.ts +5 -2
- package/dist/project/adaptation-project.js +1 -0
- package/dist/project/project-data.js +1 -1
- package/dist/project/project-detection.d.ts +3 -1
- package/dist/project/project-detection.js +10 -4
- package/dist/project/project-extension.d.ts +1 -1
- package/dist/project/project-extension.js +3 -1
- package/dist/project/project-info.d.ts +3 -1
- package/dist/project/project-info.js +6 -3
- package/dist/project/regular-project.js +17 -9
- package/dist/template/application.d.ts +2 -0
- package/dist/template/application.js +11 -9
- package/dist/template/assembly.js +4 -4
- package/dist/template/base.d.ts +2 -0
- package/dist/template/base.js +2 -30
- package/dist/template/details.d.ts +3 -1
- package/dist/template/details.js +7 -5
- package/dist/template/template-helpers.d.ts +3 -1
- package/dist/template/template-helpers.js +6 -5
- package/dist/template/theme.d.ts +3 -1
- package/dist/template/theme.js +3 -2
- package/dist/types/mem-fs-types.d.ts +1 -1
- package/dist/utils/Project.d.ts +17 -14
- package/dist/utils/Project.js +94 -72
- package/dist/utils/checkForMigration.d.ts +4 -3
- package/dist/utils/checkForMigration.js +11 -8
- package/dist/utils/file-access.d.ts +36 -34
- package/dist/utils/file-access.js +61 -93
- package/dist/utils/file-discovery.d.ts +5 -2
- package/dist/utils/file-discovery.js +6 -4
- package/dist/utils/file-system-utils.d.ts +15 -5
- package/dist/utils/file-system-utils.js +34 -11
- package/dist/utils/fs-adapter.d.ts +5 -63
- package/dist/utils/fs-adapter.js +6 -111
- package/dist/utils/manifest-and-version-utils.d.ts +3 -1
- package/dist/utils/manifest-and-version-utils.js +6 -3
- package/dist/utils/migration-utils.d.ts +3 -1
- package/dist/utils/migration-utils.js +5 -4
- package/dist/utils/project-access-adapters.d.ts +3 -1
- package/dist/utils/project-access-adapters.js +3 -2
- package/dist/utils/project-discovery.d.ts +6 -2
- package/dist/utils/project-discovery.js +44 -18
- package/dist/utils/project-readers/adaptation-project-utils.d.ts +5 -2
- package/dist/utils/project-readers/adaptation-project-utils.js +21 -16
- package/dist/utils/project-readers/backend-utils.d.ts +3 -1
- package/dist/utils/project-readers/backend-utils.js +4 -3
- package/dist/utils/project-readers/extension-project-utils.d.ts +5 -2
- package/dist/utils/project-readers/extension-project-utils.js +15 -11
- package/dist/utils/project-readers/manifest-reader.d.ts +3 -1
- package/dist/utils/project-readers/manifest-reader.js +3 -2
- package/dist/utils/project-readers/manifest-utils.d.ts +5 -2
- package/dist/utils/project-readers/manifest-utils.js +9 -6
- package/dist/utils/project-readers/package-reader.d.ts +3 -1
- package/dist/utils/project-readers/package-reader.js +3 -2
- package/dist/utils/project-readers/reuse-lib-utils.d.ts +7 -3
- package/dist/utils/project-readers/reuse-lib-utils.js +13 -7
- package/dist/utils/project-readers/webapp-path-resolver.d.ts +3 -1
- package/dist/utils/project-readers/webapp-path-resolver.js +24 -19
- package/dist/utils/service.d.ts +3 -2
- package/dist/utils/service.js +10 -6
- package/dist/utils/template/template-post-processors.d.ts +3 -1
- package/dist/utils/template/template-post-processors.js +4 -3
- package/dist/utils/template/template-renderer.d.ts +3 -1
- package/dist/utils/template/template-renderer.js +3 -2
- package/dist/utils/template-generators/file-handlers.d.ts +5 -2
- package/dist/utils/template-generators/file-handlers.js +59 -32
- package/package.json +9 -9
|
@@ -28,21 +28,29 @@ export declare class ProjectMigrator {
|
|
|
28
28
|
* @param options - Migration options object
|
|
29
29
|
* @returns Promise with fs editor, migration result, and messages
|
|
30
30
|
*/
|
|
31
|
-
static migrate(// NOSONAR - Overload for backward compatibility; use options object signature instead
|
|
32
|
-
projectRoot: string, baseUri?: string, ui5SnapshotUrl?: string, importProjectInfo?: ImportProjectInfo, vscode?: any, internalToggle?: boolean, fs?: Editor, strict?: boolean): Promise<{
|
|
33
|
-
fs: Editor;
|
|
34
|
-
result: boolean;
|
|
35
|
-
messages: Message[];
|
|
36
|
-
}>;
|
|
37
31
|
static migrate(options: MigrateOptions): Promise<{
|
|
38
32
|
fs: Editor;
|
|
39
33
|
result: boolean;
|
|
40
34
|
messages: Message[];
|
|
41
35
|
}>;
|
|
36
|
+
/**
|
|
37
|
+
* Run the migration for the resolved project info, dispatching by project type.
|
|
38
|
+
*
|
|
39
|
+
* @param editor
|
|
40
|
+
* @param projectInfo
|
|
41
|
+
* @param messages
|
|
42
|
+
* @param opts
|
|
43
|
+
* @param opts.vscode
|
|
44
|
+
* @param opts.ui5SnapshotUrl
|
|
45
|
+
* @param opts.internalToggle
|
|
46
|
+
* @param opts.strict
|
|
47
|
+
*/
|
|
48
|
+
private static runMigrationForProjectInfo;
|
|
42
49
|
/**
|
|
43
50
|
* Copy files from templates into the project
|
|
44
51
|
* Orchestrates the migration process through distinct phases
|
|
45
52
|
*
|
|
53
|
+
* @param fs - mem-fs editor
|
|
46
54
|
* @param projectInfo - Project information
|
|
47
55
|
* @param vscode - VS Code context
|
|
48
56
|
* @param ui5SnapshotUrl - UI5 snapshot URL
|
|
@@ -54,6 +62,7 @@ export declare class ProjectMigrator {
|
|
|
54
62
|
/**
|
|
55
63
|
* Copy files from templates into the project
|
|
56
64
|
*
|
|
65
|
+
* @param fs - mem-fs editor
|
|
57
66
|
* @param projectInfo
|
|
58
67
|
* @param snapshotUrl
|
|
59
68
|
*/
|
|
@@ -61,6 +70,7 @@ export declare class ProjectMigrator {
|
|
|
61
70
|
/**
|
|
62
71
|
* Copy files from templates into the project
|
|
63
72
|
*
|
|
73
|
+
* @param fs
|
|
64
74
|
* @param projectInfo
|
|
65
75
|
*/
|
|
66
76
|
private static copyLibraryFiles;
|
|
@@ -69,6 +79,7 @@ export declare class ProjectMigrator {
|
|
|
69
79
|
* Generates tsconfig.json and TypeScript devDependencies via {@link enableTypescript},
|
|
70
80
|
* then patches ui5-local.yaml and ui5-mock.yaml with the transpile middleware and task.
|
|
71
81
|
*
|
|
82
|
+
* @param fs - The mem-fs editor.
|
|
72
83
|
* @param rootPath - The project root path.
|
|
73
84
|
* @returns Messages to surface to the user after setup.
|
|
74
85
|
*/
|
|
@@ -79,6 +90,7 @@ export declare class ProjectMigrator {
|
|
|
79
90
|
* Falls back to scanning the webapp folder for .ts files directly, since after a download from ABAP
|
|
80
91
|
* the project will not yet have a tsconfig.json — it is added as part of the migration itself.
|
|
81
92
|
*
|
|
93
|
+
* @param fs - The mem-fs editor.
|
|
82
94
|
* @param rootPath - The project root path.
|
|
83
95
|
* @param webappPath - The relative path to the webapp folder.
|
|
84
96
|
* @returns True if the project contains TypeScript source files.
|
|
@@ -86,9 +98,9 @@ export declare class ProjectMigrator {
|
|
|
86
98
|
private static detectTypeScriptApp;
|
|
87
99
|
/**
|
|
88
100
|
* Scans the webapp folder for a TypeScript source file (.ts, excluding .d.ts).
|
|
89
|
-
*
|
|
90
|
-
* editor with a store is in context the mem-fs store is scanned; otherwise the real disk is read.
|
|
101
|
+
* The migration tree is loaded into the mem-fs store, so the staged files are scanned.
|
|
91
102
|
*
|
|
103
|
+
* @param fs - The mem-fs editor.
|
|
92
104
|
* @param webappFullPath - Absolute path to the webapp folder.
|
|
93
105
|
* @returns True if a non-declaration .ts file is present under the webapp folder.
|
|
94
106
|
*/
|
package/dist/ProjectMigrator.js
CHANGED
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
import { FioriElementsVersion, FileName } from './project-spec-types.js';
|
|
2
|
-
import { determineMessage, readFile, updateFile } from './utils/index.js';
|
|
3
|
-
import { createMemFsEditor,
|
|
4
|
-
import { commitFileSystemChanges } from './files/file-system.js';
|
|
2
|
+
import { determineMessage, readFile, updateFile, fileExists } from './utils/index.js';
|
|
3
|
+
import { createMemFsEditor, loadProjectIntoEditor } from './utils/fs-adapter.js';
|
|
5
4
|
import { ui5VersionRequestInfo } from '@sap-ux/ui5-info';
|
|
6
5
|
import { getAppProgrammingLanguage } from '@sap-ux/project-access';
|
|
7
6
|
import { enableTypescript, ui5TSSupport } from '@sap-ux/ui5-application-writer';
|
|
8
7
|
import { UI5Config } from '@sap-ux/ui5-config';
|
|
9
|
-
import { readdir } from 'node:fs/promises';
|
|
10
8
|
import { join } from 'node:path';
|
|
11
9
|
// Migration-specific functions
|
|
12
10
|
import { determineSourceTemplateType, checkForErrors, createMigrationErrorMessage, prepareConfigurationData, setupProjectStructure, generateAppSettings, applyAllTemplates, postProcessMigration } from './migration-process/index.js';
|
|
@@ -22,93 +20,57 @@ import { MigrationTypes } from './utils/constants.js';
|
|
|
22
20
|
import { hasStore } from './types/mem-fs-types.js';
|
|
23
21
|
import { i18nText, initI18n } from './i18n.js';
|
|
24
22
|
export class ProjectMigrator {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
projectRoot: projectRootOrOptions,
|
|
33
|
-
baseUri: baseUri ?? '',
|
|
34
|
-
ui5SnapshotUrl: ui5SnapshotUrl ?? '',
|
|
35
|
-
importProjectInfo,
|
|
36
|
-
vscode,
|
|
37
|
-
internalToggle,
|
|
38
|
-
fs,
|
|
39
|
-
strict
|
|
40
|
-
}
|
|
41
|
-
: projectRootOrOptions;
|
|
23
|
+
/**
|
|
24
|
+
* migrate project
|
|
25
|
+
*
|
|
26
|
+
* @param options - Migration options object
|
|
27
|
+
* @returns Promise with fs editor, migration result, and messages
|
|
28
|
+
*/
|
|
29
|
+
static async migrate(options) {
|
|
42
30
|
const { projectRoot, baseUri: baseUriOpt, ui5SnapshotUrl: ui5SnapshotUrlOpt, importProjectInfo: importProjectInfoOpt, vscode: vscodeOpt, internalToggle: internalToggleOpt = false, fs: fsOpt, strict: strictOpt = false } = options;
|
|
43
31
|
// Create a new isolated editor instance for this migration if not provided
|
|
44
32
|
// This enables concurrent migrations without shared state corruption
|
|
45
33
|
const ownsEditor = !fsOpt;
|
|
46
34
|
const editor = fsOpt ?? createMemFsEditor();
|
|
47
35
|
await initI18n();
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
// Update editor to the one returned from copyLibraryFiles
|
|
84
|
-
return { fs: updatedFs, result, messages };
|
|
85
|
-
}
|
|
86
|
-
else if (projectInfo.uiAdaptation) {
|
|
87
|
-
const { fs: updatedFs, messages: copyMessages, result: isSuccess } = await this.copyAdaptationFiles(projectInfo, ui5SnapshotUrlOpt);
|
|
88
|
-
messages = messages.concat(copyMessages);
|
|
89
|
-
result = isSuccess;
|
|
90
|
-
// Update editor to the one returned from copyAdaptationFiles
|
|
91
|
-
return { fs: updatedFs, result, messages };
|
|
92
|
-
}
|
|
93
|
-
else {
|
|
94
|
-
messages.push({ type: 'ERROR', description: i18nText('ERROR_FAILED_TO_GET_PROJECT_INFO') });
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
catch (e) {
|
|
98
|
-
const error = e instanceof Error ? e : new Error(String(e));
|
|
99
|
-
const useMessage = typeof e === 'object' && e !== null && 'useMessage' in e ? Boolean(e.useMessage) : false;
|
|
100
|
-
messages.push({
|
|
101
|
-
type: 'ERROR',
|
|
102
|
-
description: `Error during migration: ${determineMessage(error, undefined, useMessage)}`
|
|
103
|
-
});
|
|
104
|
-
}
|
|
105
|
-
// Return fs editor for caller to commit
|
|
106
|
-
// This matches the pattern used by other open-ux-tools writers
|
|
107
|
-
return { fs: editor, result, messages };
|
|
108
|
-
});
|
|
36
|
+
let messages = [];
|
|
37
|
+
let result = false;
|
|
38
|
+
try {
|
|
39
|
+
// Load the project tree into mem-fs so existence checks see untracked files
|
|
40
|
+
// on disk and migration writes never silently overwrite them.
|
|
41
|
+
await loadProjectIntoEditor(editor, projectRoot);
|
|
42
|
+
// Load or fetch project information
|
|
43
|
+
const { projectInfo, messages: projectInfoMessages } = await loadOrFetchProjectInfo(projectRoot, importProjectInfoOpt, editor);
|
|
44
|
+
messages = messages.concat(projectInfoMessages);
|
|
45
|
+
projectInfo.baseUri = baseUriOpt;
|
|
46
|
+
// Resolve UI5 versions for migration
|
|
47
|
+
const ui5Versions = await resolveUI5VersionsForMigration(projectInfo, ui5SnapshotUrlOpt);
|
|
48
|
+
projectInfo.localUI5Version = ui5Versions?.[0]?.version;
|
|
49
|
+
// ui5Version left as-is from project/neo-app data
|
|
50
|
+
// Validate project is suitable for migration (not a Fiori app in CAP project)
|
|
51
|
+
await validateProjectForMigration(editor, projectRoot);
|
|
52
|
+
const dispatch = await this.runMigrationForProjectInfo(editor, projectInfo, messages, {
|
|
53
|
+
vscode: vscodeOpt,
|
|
54
|
+
ui5SnapshotUrl: ui5SnapshotUrlOpt,
|
|
55
|
+
internalToggle: internalToggleOpt,
|
|
56
|
+
strict: strictOpt
|
|
57
|
+
});
|
|
58
|
+
messages = dispatch.messages;
|
|
59
|
+
result = dispatch.result;
|
|
60
|
+
}
|
|
61
|
+
catch (e) {
|
|
62
|
+
const error = e instanceof Error ? e : new Error(String(e));
|
|
63
|
+
const useMessage = typeof e === 'object' && e !== null && 'useMessage' in e ? Boolean(e.useMessage) : false;
|
|
64
|
+
messages.push({
|
|
65
|
+
type: 'ERROR',
|
|
66
|
+
description: `Error during migration: ${determineMessage(error, undefined, useMessage)}`
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
const migrationResult = { fs: editor, result, messages };
|
|
70
|
+
// Commit only when we own the editor; otherwise the caller commits (matches other writers).
|
|
109
71
|
if (ownsEditor && migrationResult.result) {
|
|
110
72
|
try {
|
|
111
|
-
await
|
|
73
|
+
await new Promise((resolve, reject) => migrationResult.fs.commit((error) => (error ? reject(error) : resolve())));
|
|
112
74
|
}
|
|
113
75
|
catch (error) {
|
|
114
76
|
migrationResult.result = false;
|
|
@@ -120,10 +82,45 @@ export class ProjectMigrator {
|
|
|
120
82
|
}
|
|
121
83
|
return migrationResult;
|
|
122
84
|
}
|
|
85
|
+
/**
|
|
86
|
+
* Run the migration for the resolved project info, dispatching by project type.
|
|
87
|
+
*
|
|
88
|
+
* @param editor
|
|
89
|
+
* @param projectInfo
|
|
90
|
+
* @param messages
|
|
91
|
+
* @param opts
|
|
92
|
+
* @param opts.vscode
|
|
93
|
+
* @param opts.ui5SnapshotUrl
|
|
94
|
+
* @param opts.internalToggle
|
|
95
|
+
* @param opts.strict
|
|
96
|
+
*/
|
|
97
|
+
static async runMigrationForProjectInfo(editor, projectInfo, messages, opts) {
|
|
98
|
+
const isSupportedApp = projectInfo.isSAPApp ||
|
|
99
|
+
projectInfo.FEVersion === FioriElementsVersion.v2 ||
|
|
100
|
+
projectInfo.FEVersion === FioriElementsVersion.v4 ||
|
|
101
|
+
projectInfo.type === MigrationTypes.projectExtension;
|
|
102
|
+
if (isSupportedApp && checkForErrors(messages)) {
|
|
103
|
+
const { messages: copyMessages, result } = await this.copyCommonFiles(editor, projectInfo, opts.vscode, opts.ui5SnapshotUrl, opts.internalToggle, opts.strict);
|
|
104
|
+
return { result, messages: messages.concat(copyMessages) };
|
|
105
|
+
}
|
|
106
|
+
if (projectInfo.type === MigrationTypes.library) {
|
|
107
|
+
const { messages: copyMessages, result } = await this.copyLibraryFiles(editor, projectInfo);
|
|
108
|
+
return { result, messages: messages.concat(copyMessages) };
|
|
109
|
+
}
|
|
110
|
+
if (projectInfo.uiAdaptation) {
|
|
111
|
+
const { messages: copyMessages, result } = await this.copyAdaptationFiles(editor, projectInfo, opts.ui5SnapshotUrl);
|
|
112
|
+
return { result, messages: messages.concat(copyMessages) };
|
|
113
|
+
}
|
|
114
|
+
return {
|
|
115
|
+
result: false,
|
|
116
|
+
messages: messages.concat({ type: 'ERROR', description: i18nText('ERROR_FAILED_TO_GET_PROJECT_INFO') })
|
|
117
|
+
};
|
|
118
|
+
}
|
|
123
119
|
/**
|
|
124
120
|
* Copy files from templates into the project
|
|
125
121
|
* Orchestrates the migration process through distinct phases
|
|
126
122
|
*
|
|
123
|
+
* @param fs - mem-fs editor
|
|
127
124
|
* @param projectInfo - Project information
|
|
128
125
|
* @param vscode - VS Code context
|
|
129
126
|
* @param ui5SnapshotUrl - UI5 snapshot URL
|
|
@@ -131,19 +128,20 @@ export class ProjectMigrator {
|
|
|
131
128
|
* @param strict - Enable strict validation mode (WARNINGs become ERRORs for critical issues)
|
|
132
129
|
* @returns Migration result with status and messages
|
|
133
130
|
*/
|
|
134
|
-
static async copyCommonFiles(projectInfo, vscode, ui5SnapshotUrl, internalToggle = false, strict = false) {
|
|
131
|
+
static async copyCommonFiles(fs, projectInfo, vscode, ui5SnapshotUrl, internalToggle = false, strict = false) {
|
|
135
132
|
const messages = [];
|
|
136
133
|
const { isSAPApp = false, rootPath, destination, neoappDestinations, firstNeoAppDestination } = projectInfo;
|
|
137
134
|
try {
|
|
138
135
|
// Detect TypeScript project
|
|
139
|
-
const isTypeScriptApp = await ProjectMigrator.detectTypeScriptApp(rootPath, projectInfo.webappPath);
|
|
136
|
+
const isTypeScriptApp = await ProjectMigrator.detectTypeScriptApp(fs, rootPath, projectInfo.webappPath);
|
|
140
137
|
// Prepare configuration data
|
|
141
|
-
const configData = await prepareConfigurationData(projectInfo, projectInfo.ui5Version, isTypeScriptApp);
|
|
138
|
+
const configData = await prepareConfigurationData(fs, projectInfo, projectInfo.ui5Version, isTypeScriptApp);
|
|
142
139
|
// Phase 1: Setup project structure
|
|
143
|
-
const { webappPath, keepIndex } = await setupProjectStructure(projectInfo, rootPath);
|
|
140
|
+
const { webappPath, keepIndex } = await setupProjectStructure(fs, projectInfo, rootPath);
|
|
144
141
|
projectInfo.webappPath = webappPath;
|
|
145
142
|
// Phase 2: Assemble template data
|
|
146
143
|
const templateContext = await assembleTemplateData({
|
|
144
|
+
fs,
|
|
147
145
|
projectInfo,
|
|
148
146
|
rootPath,
|
|
149
147
|
projectData: configData.projectData,
|
|
@@ -193,6 +191,7 @@ export class ProjectMigrator {
|
|
|
193
191
|
// Phase 3: Generate app settings
|
|
194
192
|
const sourceTemplateType = determineSourceTemplateType(projectInfo, MigrationTypes);
|
|
195
193
|
await generateAppSettings({
|
|
194
|
+
fs,
|
|
196
195
|
rootPath,
|
|
197
196
|
templateData: templateContext.templateData,
|
|
198
197
|
destination,
|
|
@@ -207,6 +206,7 @@ export class ProjectMigrator {
|
|
|
207
206
|
});
|
|
208
207
|
// Phase 4: Apply all templates
|
|
209
208
|
await applyAllTemplates({
|
|
209
|
+
fs,
|
|
210
210
|
projectInfo,
|
|
211
211
|
rootPath,
|
|
212
212
|
templateData: templateContext.templateData,
|
|
@@ -220,6 +220,7 @@ export class ProjectMigrator {
|
|
|
220
220
|
});
|
|
221
221
|
// Phase 5: Post-processing
|
|
222
222
|
await postProcessMigration({
|
|
223
|
+
fs,
|
|
223
224
|
projectInfo,
|
|
224
225
|
rootPath,
|
|
225
226
|
manifestJSON: templateContext.manifestJSON,
|
|
@@ -232,7 +233,7 @@ export class ProjectMigrator {
|
|
|
232
233
|
});
|
|
233
234
|
// Phase 6: TypeScript setup (if TypeScript app detected)
|
|
234
235
|
if (isTypeScriptApp) {
|
|
235
|
-
const tsMessages = await ProjectMigrator.setupTypeScript(rootPath);
|
|
236
|
+
const tsMessages = await ProjectMigrator.setupTypeScript(fs, rootPath);
|
|
236
237
|
messages.push(...tsMessages);
|
|
237
238
|
}
|
|
238
239
|
return { result: checkForErrors(messages), messages };
|
|
@@ -247,32 +248,35 @@ export class ProjectMigrator {
|
|
|
247
248
|
/**
|
|
248
249
|
* Copy files from templates into the project
|
|
249
250
|
*
|
|
251
|
+
* @param fs - mem-fs editor
|
|
250
252
|
* @param projectInfo
|
|
251
253
|
* @param snapshotUrl
|
|
252
254
|
*/
|
|
253
|
-
static async copyAdaptationFiles(projectInfo, snapshotUrl) {
|
|
254
|
-
return copyAdaptationFiles(projectInfo, snapshotUrl
|
|
255
|
+
static async copyAdaptationFiles(fs, projectInfo, snapshotUrl) {
|
|
256
|
+
return copyAdaptationFiles(fs, projectInfo, snapshotUrl);
|
|
255
257
|
}
|
|
256
258
|
/**
|
|
257
259
|
* Copy files from templates into the project
|
|
258
260
|
*
|
|
261
|
+
* @param fs
|
|
259
262
|
* @param projectInfo
|
|
260
263
|
*/
|
|
261
|
-
static async copyLibraryFiles(projectInfo) {
|
|
262
|
-
return copyLibraryFiles(projectInfo);
|
|
264
|
+
static async copyLibraryFiles(fs, projectInfo) {
|
|
265
|
+
return copyLibraryFiles(fs, projectInfo);
|
|
263
266
|
}
|
|
264
267
|
/**
|
|
265
268
|
* Configures a downloaded TypeScript app for local development.
|
|
266
269
|
* Generates tsconfig.json and TypeScript devDependencies via {@link enableTypescript},
|
|
267
270
|
* then patches ui5-local.yaml and ui5-mock.yaml with the transpile middleware and task.
|
|
268
271
|
*
|
|
272
|
+
* @param fs - The mem-fs editor.
|
|
269
273
|
* @param rootPath - The project root path.
|
|
270
274
|
* @returns Messages to surface to the user after setup.
|
|
271
275
|
*/
|
|
272
|
-
static async setupTypeScript(rootPath) {
|
|
276
|
+
static async setupTypeScript(fs, rootPath) {
|
|
273
277
|
const messages = [];
|
|
274
278
|
try {
|
|
275
|
-
await enableTypescript(rootPath,
|
|
279
|
+
await enableTypescript(rootPath, fs);
|
|
276
280
|
}
|
|
277
281
|
catch (err) {
|
|
278
282
|
messages.push({
|
|
@@ -284,14 +288,12 @@ export class ProjectMigrator {
|
|
|
284
288
|
// Check and update ui5*.yaml files sequentially - order doesn't matter but list is small
|
|
285
289
|
for (const yamlName of [FileName.UI5LocalYaml, FileName.UI5MockYaml]) {
|
|
286
290
|
const yamlPath = join(rootPath, yamlName);
|
|
287
|
-
if (
|
|
288
|
-
|
|
289
|
-
// readFile and updateFile are sync mem-fs operations
|
|
290
|
-
const yamlContent = readFile(yamlPath);
|
|
291
|
+
if (fileExists(fs, yamlPath)) {
|
|
292
|
+
const yamlContent = readFile(fs, yamlPath);
|
|
291
293
|
const yamlConfig = await UI5Config.newInstance(yamlContent); // NOSONAR - Sequential YAML parsing required
|
|
292
294
|
yamlConfig.addCustomMiddleware([ui5TSSupport.middleware]);
|
|
293
295
|
yamlConfig.addCustomTasks([ui5TSSupport.task]);
|
|
294
|
-
updateFile(yamlPath, yamlConfig.toString());
|
|
296
|
+
updateFile(fs, yamlPath, yamlConfig.toString());
|
|
295
297
|
}
|
|
296
298
|
}
|
|
297
299
|
messages.push({
|
|
@@ -306,11 +308,12 @@ export class ProjectMigrator {
|
|
|
306
308
|
* Falls back to scanning the webapp folder for .ts files directly, since after a download from ABAP
|
|
307
309
|
* the project will not yet have a tsconfig.json — it is added as part of the migration itself.
|
|
308
310
|
*
|
|
311
|
+
* @param fs - The mem-fs editor.
|
|
309
312
|
* @param rootPath - The project root path.
|
|
310
313
|
* @param webappPath - The relative path to the webapp folder.
|
|
311
314
|
* @returns True if the project contains TypeScript source files.
|
|
312
315
|
*/
|
|
313
|
-
static async detectTypeScriptApp(rootPath, webappPath) {
|
|
316
|
+
static async detectTypeScriptApp(fs, rootPath, webappPath) {
|
|
314
317
|
const webappFullPath = join(rootPath, webappPath);
|
|
315
318
|
// Try getAppProgrammingLanguage first (needs tsconfig.json and package.json)
|
|
316
319
|
let isTypeScript = false;
|
|
@@ -324,39 +327,34 @@ export class ProjectMigrator {
|
|
|
324
327
|
if (isTypeScript) {
|
|
325
328
|
return true;
|
|
326
329
|
}
|
|
327
|
-
return ProjectMigrator.webappHasTypeScriptFile(webappFullPath);
|
|
330
|
+
return ProjectMigrator.webappHasTypeScriptFile(fs, webappFullPath);
|
|
328
331
|
}
|
|
329
332
|
/**
|
|
330
333
|
* Scans the webapp folder for a TypeScript source file (.ts, excluding .d.ts).
|
|
331
|
-
*
|
|
332
|
-
* editor with a store is in context the mem-fs store is scanned; otherwise the real disk is read.
|
|
334
|
+
* The migration tree is loaded into the mem-fs store, so the staged files are scanned.
|
|
333
335
|
*
|
|
336
|
+
* @param fs - The mem-fs editor.
|
|
334
337
|
* @param webappFullPath - Absolute path to the webapp folder.
|
|
335
338
|
* @returns True if a non-declaration .ts file is present under the webapp folder.
|
|
336
339
|
*/
|
|
337
|
-
static
|
|
340
|
+
static webappHasTypeScriptFile(fs, webappFullPath) {
|
|
338
341
|
const isTypeScriptFile = (filePath) => filePath.endsWith('.ts') && !filePath.endsWith('.d.ts');
|
|
339
|
-
|
|
340
|
-
if (editor && hasStore(editor)) {
|
|
341
|
-
// mem-fs mode: scan staged files under the webapp folder (paths use forward slashes)
|
|
342
|
-
const normalizedPrefix = webappFullPath.replaceAll('\\', '/').replace(/\/?$/, '/');
|
|
343
|
-
let found = false;
|
|
344
|
-
editor.store.each((file) => {
|
|
345
|
-
if (file.state === 'deleted') {
|
|
346
|
-
return;
|
|
347
|
-
}
|
|
348
|
-
const normalizedFilePath = file.path.replaceAll('\\', '/');
|
|
349
|
-
if (normalizedFilePath.startsWith(normalizedPrefix) && isTypeScriptFile(normalizedFilePath)) {
|
|
350
|
-
found = true;
|
|
351
|
-
}
|
|
352
|
-
});
|
|
353
|
-
return found;
|
|
354
|
-
}
|
|
355
|
-
// No editor context: scan the real filesystem
|
|
356
|
-
if (!(await exists(webappFullPath))) {
|
|
342
|
+
if (!hasStore(fs)) {
|
|
357
343
|
return false;
|
|
358
344
|
}
|
|
359
|
-
|
|
345
|
+
// Scan staged files under the webapp folder (paths use forward slashes)
|
|
346
|
+
const normalizedPrefix = webappFullPath.replaceAll('\\', '/').replace(/\/?$/, '/');
|
|
347
|
+
let found = false;
|
|
348
|
+
fs.store.each((file) => {
|
|
349
|
+
if (file.state === 'deleted') {
|
|
350
|
+
return;
|
|
351
|
+
}
|
|
352
|
+
const normalizedFilePath = file.path.replaceAll('\\', '/');
|
|
353
|
+
if (normalizedFilePath.startsWith(normalizedPrefix) && isTypeScriptFile(normalizedFilePath)) {
|
|
354
|
+
found = true;
|
|
355
|
+
}
|
|
356
|
+
});
|
|
357
|
+
return found;
|
|
360
358
|
}
|
|
361
359
|
}
|
|
362
360
|
//# sourceMappingURL=ProjectMigrator.js.map
|
|
@@ -37,14 +37,14 @@ function addMockserverMiddleware(orderedYaml, templateData) {
|
|
|
37
37
|
}
|
|
38
38
|
}
|
|
39
39
|
};
|
|
40
|
-
// Find index of fiori-tools-proxy and insert
|
|
40
|
+
// Find index of fiori-tools-proxy and insert after it
|
|
41
41
|
const proxyIndex = orderedYaml.server.customMiddleware.findIndex((mw) => mw.name === 'fiori-tools-proxy');
|
|
42
42
|
if (proxyIndex >= 0) {
|
|
43
|
-
orderedYaml.server.customMiddleware.splice(proxyIndex, 0, mockserverMiddleware);
|
|
43
|
+
orderedYaml.server.customMiddleware.splice(proxyIndex + 1, 0, mockserverMiddleware);
|
|
44
44
|
}
|
|
45
45
|
else {
|
|
46
|
-
// If proxy not found, add at
|
|
47
|
-
orderedYaml.server.customMiddleware.
|
|
46
|
+
// If proxy not found, add at end
|
|
47
|
+
orderedYaml.server.customMiddleware.push(mockserverMiddleware);
|
|
48
48
|
}
|
|
49
49
|
}
|
|
50
50
|
/**
|
|
@@ -202,22 +202,68 @@ export async function generateUI5LocalYamlContent(options) {
|
|
|
202
202
|
*/
|
|
203
203
|
export async function generateUI5MockYamlContent(templateData, webappPath, setUI5Version) {
|
|
204
204
|
const config = await createBaseConfig(templateData);
|
|
205
|
-
// Add fiori-tools-proxy middleware with
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
path: ['/resources', '/test-resources'],
|
|
211
|
-
url: templateData.ui5Yaml?.ui5Url || ''
|
|
212
|
-
}
|
|
213
|
-
};
|
|
214
|
-
// Add UI5 version to proxy if provided and setUI5Version is true
|
|
215
|
-
if (setUI5Version && templateData.ui5Yaml?.ui5Version) {
|
|
216
|
-
proxyConfig.ui5.version = templateData.ui5Yaml.ui5Version;
|
|
217
|
-
}
|
|
205
|
+
// Add fiori-tools-proxy middleware with the main backend (ui5-mock.yaml uses only the
|
|
206
|
+
// primary backend, not the per-service neo-app destinations that ui5.yaml carries).
|
|
207
|
+
const mainBackend = buildMainBackend(templateData);
|
|
208
|
+
const backends = mainBackend ? [mainBackend] : [];
|
|
209
|
+
const proxyConfig = buildProxyConfig(backends, templateData, setUI5Version);
|
|
218
210
|
config.addFioriToolsProxyMiddleware(proxyConfig);
|
|
219
211
|
// Add fiori-tools-appreload middleware
|
|
220
212
|
config.addFioriToolsAppReloadMiddleware();
|
|
221
|
-
|
|
213
|
+
// Add fiori-tools-preview middleware if configured
|
|
214
|
+
const previewMiddleware = buildPreviewMiddleware(templateData);
|
|
215
|
+
if (previewMiddleware) {
|
|
216
|
+
config.addCustomMiddleware(previewMiddleware);
|
|
217
|
+
}
|
|
218
|
+
const yamlContent = config.toString();
|
|
219
|
+
const yamlJson = parse(yamlContent);
|
|
220
|
+
const orderedYaml = { specVersion: '4.0' };
|
|
221
|
+
Object.keys(yamlJson).forEach((key) => {
|
|
222
|
+
orderedYaml[key] = yamlJson[key];
|
|
223
|
+
});
|
|
224
|
+
// Add sap-fe-mockserver middleware (the core of ui5-mock.yaml) when a service is configured.
|
|
225
|
+
if (templateData.ui5Yaml?.servicePath) {
|
|
226
|
+
addMockServerServicesMiddleware(orderedYaml, templateData);
|
|
227
|
+
}
|
|
228
|
+
// Apply webappPath if provided
|
|
229
|
+
if (webappPath) {
|
|
230
|
+
setWebappPath(orderedYaml, webappPath);
|
|
231
|
+
setAppreloadPath(orderedYaml, webappPath);
|
|
232
|
+
}
|
|
233
|
+
return stringify(orderedYaml);
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* Add a sap-fe-mockserver middleware (mountPath/services[] shape used by ui5-mock.yaml)
|
|
237
|
+
* before the fiori-tools-proxy middleware.
|
|
238
|
+
*
|
|
239
|
+
* @param orderedYaml - Parsed YAML object to mutate
|
|
240
|
+
* @param templateData - Template data with the service/mock configuration
|
|
241
|
+
*/
|
|
242
|
+
function addMockServerServicesMiddleware(orderedYaml, templateData) {
|
|
243
|
+
orderedYaml.server ??= { customMiddleware: [] };
|
|
244
|
+
orderedYaml.server.customMiddleware ??= [];
|
|
245
|
+
const mockserverMiddleware = {
|
|
246
|
+
name: 'sap-fe-mockserver',
|
|
247
|
+
beforeMiddleware: 'fiori-tools-proxy',
|
|
248
|
+
configuration: {
|
|
249
|
+
mountPath: '/',
|
|
250
|
+
services: [
|
|
251
|
+
{
|
|
252
|
+
urlPath: (templateData.ui5Yaml?.servicePath ?? '').replace(/\/$/, ''),
|
|
253
|
+
metadataPath: templateData.ui5Yaml?.metadataXmlPath || '',
|
|
254
|
+
mockdataPath: templateData.ui5Yaml?.mockdataRootPath || '',
|
|
255
|
+
generateMockData: templateData.ui5Yaml?.generateMockData ?? true,
|
|
256
|
+
annotations: []
|
|
257
|
+
}
|
|
258
|
+
]
|
|
259
|
+
}
|
|
260
|
+
};
|
|
261
|
+
const proxyIndex = orderedYaml.server.customMiddleware.findIndex((mw) => mw.name === 'fiori-tools-proxy');
|
|
262
|
+
if (proxyIndex >= 0) {
|
|
263
|
+
orderedYaml.server.customMiddleware.splice(proxyIndex + 1, 0, mockserverMiddleware);
|
|
264
|
+
}
|
|
265
|
+
else {
|
|
266
|
+
orderedYaml.server.customMiddleware.push(mockserverMiddleware);
|
|
267
|
+
}
|
|
222
268
|
}
|
|
223
269
|
//# sourceMappingURL=ui5-config-adapter.js.map
|
|
@@ -7,12 +7,12 @@
|
|
|
7
7
|
* @returns Backend configuration or undefined if not configured
|
|
8
8
|
*/
|
|
9
9
|
export function buildMainBackend(templateData) {
|
|
10
|
-
if (!templateData.ui5Yaml?.proxyPath || !templateData.ui5Yaml?.proxyHost) {
|
|
10
|
+
if (!templateData.ui5Yaml?.proxyPath || (!templateData.ui5Yaml?.proxyHost && !templateData.ui5Yaml?.destination)) {
|
|
11
11
|
return undefined;
|
|
12
12
|
}
|
|
13
13
|
const backend = {
|
|
14
14
|
path: templateData.ui5Yaml.proxyPath,
|
|
15
|
-
url: templateData.ui5Yaml.proxyHost
|
|
15
|
+
url: templateData.ui5Yaml.proxyHost ?? ''
|
|
16
16
|
};
|
|
17
17
|
// Add optional properties
|
|
18
18
|
if (templateData.ui5Yaml.client) {
|
|
@@ -49,15 +49,8 @@ export function buildProxyConfig(backends, templateData, setUI5Version) {
|
|
|
49
49
|
url: templateData.ui5Yaml?.ui5Url || ''
|
|
50
50
|
}
|
|
51
51
|
};
|
|
52
|
-
// Add UI5 version to proxy config when setUI5Version is true
|
|
53
|
-
// This matches the behavior in tools-suite master for ui5-mock.yaml
|
|
54
|
-
// Skip if version is a placeholder/fallback value like "snapshot-version"
|
|
55
52
|
if (setUI5Version && templateData.ui5Yaml?.ui5Version) {
|
|
56
|
-
|
|
57
|
-
// Only add real versions, not placeholder values
|
|
58
|
-
if (version && !version.includes('snapshot-version')) {
|
|
59
|
-
proxyConfig.ui5.version = version;
|
|
60
|
-
}
|
|
53
|
+
proxyConfig.ui5.version = templateData.ui5Yaml.ui5Version;
|
|
61
54
|
}
|
|
62
55
|
return proxyConfig;
|
|
63
56
|
}
|
|
@@ -1,10 +1,12 @@
|
|
|
1
|
+
import type { Editor } from 'mem-fs-editor';
|
|
1
2
|
import type { ImportProjectInfo } from '../types.js';
|
|
2
3
|
/**
|
|
3
4
|
* Updates the .extconfig.json file for extension projects
|
|
4
5
|
* Handles WebIDE Personal Edition migration and destination updates
|
|
5
6
|
*
|
|
7
|
+
* @param fs - mem-fs editor
|
|
6
8
|
* @param rootPath - Root path of the project
|
|
7
9
|
* @param projectInfo - Project information containing extension settings
|
|
8
10
|
*/
|
|
9
|
-
export declare function updateExtConfigJson(rootPath: string, projectInfo: ImportProjectInfo):
|
|
11
|
+
export declare function updateExtConfigJson(fs: Editor, rootPath: string, projectInfo: ImportProjectInfo): void;
|
|
10
12
|
//# sourceMappingURL=extension.d.ts.map
|
|
@@ -5,10 +5,11 @@ import { FileName } from '../project-spec-types.js';
|
|
|
5
5
|
* Updates the .extconfig.json file for extension projects
|
|
6
6
|
* Handles WebIDE Personal Edition migration and destination updates
|
|
7
7
|
*
|
|
8
|
+
* @param fs - mem-fs editor
|
|
8
9
|
* @param rootPath - Root path of the project
|
|
9
10
|
* @param projectInfo - Project information containing extension settings
|
|
10
11
|
*/
|
|
11
|
-
export
|
|
12
|
+
export function updateExtConfigJson(fs, rootPath, projectInfo) {
|
|
12
13
|
let extensionProjectSettingsJSON;
|
|
13
14
|
let deleteProjectJson = false;
|
|
14
15
|
try {
|
|
@@ -52,10 +53,10 @@ export async function updateExtConfigJson(rootPath, projectInfo) {
|
|
|
52
53
|
}
|
|
53
54
|
}
|
|
54
55
|
// write .extconfig.json for extension project
|
|
55
|
-
updateJSON(join(rootPath, FileName.ExtConfigJson), extensionProjectSettingsJSON);
|
|
56
|
+
updateJSON(fs, join(rootPath, FileName.ExtConfigJson), extensionProjectSettingsJSON);
|
|
56
57
|
const projectJsonPath = join(rootPath, '.project.json');
|
|
57
|
-
if (deleteProjectJson && (
|
|
58
|
-
deleteFile(projectJsonPath);
|
|
58
|
+
if (deleteProjectJson && fileExists(fs, projectJsonPath)) {
|
|
59
|
+
deleteFile(fs, projectJsonPath);
|
|
59
60
|
}
|
|
60
61
|
}
|
|
61
62
|
//# sourceMappingURL=extension.js.map
|