@sap-ux/fiori-migration-writer 0.0.5 → 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.
Files changed (108) hide show
  1. package/dist/ProjectMigrator.d.ts +20 -8
  2. package/dist/ProjectMigrator.js +121 -123
  3. package/dist/adapters/ui5-config-adapter.js +64 -18
  4. package/dist/adapters/ui5-config-helpers.js +3 -10
  5. package/dist/components/extension.d.ts +3 -1
  6. package/dist/components/extension.js +5 -4
  7. package/dist/config/backend-i18n.d.ts +27 -6
  8. package/dist/config/backend-i18n.js +5 -11
  9. package/dist/config/flp/intent.d.ts +6 -3
  10. package/dist/config/flp/intent.js +6 -4
  11. package/dist/config/flp/sandbox.d.ts +3 -1
  12. package/dist/config/flp/sandbox.js +17 -12
  13. package/dist/config/launch-config.d.ts +4 -3
  14. package/dist/config/launch-config.js +5 -16
  15. package/dist/config/manifest-update.d.ts +21 -1
  16. package/dist/config/manifest-update.js +7 -12
  17. package/dist/config/package-json.d.ts +3 -1
  18. package/dist/config/package-json.js +15 -9
  19. package/dist/config/ui5-yaml.d.ts +9 -4
  20. package/dist/config/ui5-yaml.js +14 -10
  21. package/dist/data/sap-libraries.d.ts +3 -1
  22. package/dist/data/sap-libraries.js +4 -3
  23. package/dist/data/ui5-version.js +1 -1
  24. package/dist/files/project-files.d.ts +4 -3
  25. package/dist/files/project-files.js +10 -16
  26. package/dist/files/webapp.d.ts +5 -2
  27. package/dist/files/webapp.js +30 -35
  28. package/dist/index.d.ts +2 -2
  29. package/dist/index.js +2 -2
  30. package/dist/migration-process/configuration.d.ts +3 -1
  31. package/dist/migration-process/configuration.js +3 -2
  32. package/dist/migration-process/legacy-helpers.d.ts +3 -1
  33. package/dist/migration-process/legacy-helpers.js +19 -32
  34. package/dist/migration-process/legacy.d.ts +3 -1
  35. package/dist/migration-process/legacy.js +66 -79
  36. package/dist/migration-process/migration-phases.d.ts +6 -1
  37. package/dist/migration-process/migration-phases.js +26 -14
  38. package/dist/migration-process/setup.d.ts +9 -6
  39. package/dist/migration-process/setup.js +19 -10
  40. package/dist/migration-process/validation.d.ts +5 -2
  41. package/dist/migration-process/validation.js +6 -4
  42. package/dist/migration-types.d.ts +5 -2
  43. package/dist/project/adaptation-project.js +1 -0
  44. package/dist/project/project-data.js +1 -1
  45. package/dist/project/project-detection.d.ts +3 -1
  46. package/dist/project/project-detection.js +10 -4
  47. package/dist/project/project-extension.d.ts +1 -1
  48. package/dist/project/project-extension.js +3 -1
  49. package/dist/project/project-info.d.ts +3 -1
  50. package/dist/project/project-info.js +6 -3
  51. package/dist/project/regular-project.js +17 -9
  52. package/dist/template/application.d.ts +2 -0
  53. package/dist/template/application.js +11 -9
  54. package/dist/template/assembly.js +4 -4
  55. package/dist/template/base.d.ts +2 -0
  56. package/dist/template/base.js +2 -30
  57. package/dist/template/details.d.ts +3 -1
  58. package/dist/template/details.js +7 -5
  59. package/dist/template/template-helpers.d.ts +3 -1
  60. package/dist/template/template-helpers.js +6 -5
  61. package/dist/template/theme.d.ts +3 -1
  62. package/dist/template/theme.js +3 -2
  63. package/dist/types/mem-fs-types.d.ts +1 -1
  64. package/dist/utils/Project.d.ts +17 -14
  65. package/dist/utils/Project.js +94 -72
  66. package/dist/utils/checkForMigration.d.ts +4 -3
  67. package/dist/utils/checkForMigration.js +11 -8
  68. package/dist/utils/file-access.d.ts +36 -34
  69. package/dist/utils/file-access.js +61 -93
  70. package/dist/utils/file-discovery.d.ts +5 -2
  71. package/dist/utils/file-discovery.js +6 -4
  72. package/dist/utils/file-system-utils.d.ts +15 -5
  73. package/dist/utils/file-system-utils.js +34 -11
  74. package/dist/utils/fs-adapter.d.ts +5 -63
  75. package/dist/utils/fs-adapter.js +6 -111
  76. package/dist/utils/manifest-and-version-utils.d.ts +3 -1
  77. package/dist/utils/manifest-and-version-utils.js +6 -3
  78. package/dist/utils/migration-utils.d.ts +3 -1
  79. package/dist/utils/migration-utils.js +5 -4
  80. package/dist/utils/project-access-adapters.d.ts +3 -1
  81. package/dist/utils/project-access-adapters.js +3 -2
  82. package/dist/utils/project-discovery.d.ts +6 -2
  83. package/dist/utils/project-discovery.js +44 -18
  84. package/dist/utils/project-readers/adaptation-project-utils.d.ts +5 -2
  85. package/dist/utils/project-readers/adaptation-project-utils.js +21 -16
  86. package/dist/utils/project-readers/backend-utils.d.ts +3 -1
  87. package/dist/utils/project-readers/backend-utils.js +4 -3
  88. package/dist/utils/project-readers/extension-project-utils.d.ts +5 -2
  89. package/dist/utils/project-readers/extension-project-utils.js +15 -11
  90. package/dist/utils/project-readers/manifest-reader.d.ts +3 -1
  91. package/dist/utils/project-readers/manifest-reader.js +3 -2
  92. package/dist/utils/project-readers/manifest-utils.d.ts +5 -2
  93. package/dist/utils/project-readers/manifest-utils.js +9 -6
  94. package/dist/utils/project-readers/package-reader.d.ts +3 -1
  95. package/dist/utils/project-readers/package-reader.js +3 -2
  96. package/dist/utils/project-readers/reuse-lib-utils.d.ts +7 -3
  97. package/dist/utils/project-readers/reuse-lib-utils.js +13 -7
  98. package/dist/utils/project-readers/webapp-path-resolver.d.ts +3 -1
  99. package/dist/utils/project-readers/webapp-path-resolver.js +24 -19
  100. package/dist/utils/service.d.ts +3 -2
  101. package/dist/utils/service.js +10 -6
  102. package/dist/utils/template/template-post-processors.d.ts +3 -1
  103. package/dist/utils/template/template-post-processors.js +4 -3
  104. package/dist/utils/template/template-renderer.d.ts +3 -1
  105. package/dist/utils/template/template-renderer.js +3 -2
  106. package/dist/utils/template-generators/file-handlers.d.ts +5 -2
  107. package/dist/utils/template-generators/file-handlers.js +59 -32
  108. package/package.json +4 -4
@@ -28,7 +28,7 @@ export async function resolveUI5VersionsForMigration(projectInfo, ui5SnapshotUrl
28
28
  onlyVersionNumbers: true,
29
29
  onlyNpmVersion: true,
30
30
  ui5SelectedVersion: ui5VersionMinForProject,
31
- ...(ui5SnapshotUrl && { url: ui5SnapshotUrl })
31
+ ...(ui5SnapshotUrl && { snapshotVersionsHost: ui5SnapshotUrl })
32
32
  });
33
33
  return ui5Versions;
34
34
  }
@@ -7,12 +7,12 @@ import type { ImportProjectInfo, Message } from '../types.js';
7
7
  /**
8
8
  * Copy adaptation (extension) project files from templates
9
9
  *
10
+ * @param fs - mem-fs-editor instance for file operations
10
11
  * @param projectInfo - Project import information
11
12
  * @param snapshotUrl - URL for UI5 snapshot version
12
- * @param fs - mem-fs-editor instance for file operations
13
13
  * @returns Result object with fs editor, success status and messages
14
14
  */
15
- export declare function copyAdaptationFiles(projectInfo: ImportProjectInfo, snapshotUrl: string, fs: Editor | undefined): Promise<{
15
+ export declare function copyAdaptationFiles(fs: Editor, projectInfo: ImportProjectInfo, snapshotUrl: string): Promise<{
16
16
  fs: Editor;
17
17
  result: boolean;
18
18
  messages: Message[];
@@ -20,10 +20,11 @@ export declare function copyAdaptationFiles(projectInfo: ImportProjectInfo, snap
20
20
  /**
21
21
  * Copy library project files from templates
22
22
  *
23
+ * @param fs - mem-fs editor
23
24
  * @param projectInfo - Project import information
24
25
  * @returns Result object with fs editor, success status and messages
25
26
  */
26
- export declare function copyLibraryFiles(projectInfo: ImportProjectInfo): Promise<{
27
+ export declare function copyLibraryFiles(fs: Editor, projectInfo: ImportProjectInfo): Promise<{
27
28
  fs: Editor;
28
29
  result: boolean;
29
30
  messages: Message[];
@@ -11,20 +11,18 @@ import { TemplateFileName, templatesDirPath } from '../index.js';
11
11
  import { devDependencies, ui5Dependencies, getUI5Version, determineMessage, generateToolsId, getLibraryTemplatesMap } from '../utils/common.js';
12
12
  import { ui5VersionRequestInfo } from '@sap-ux/ui5-info';
13
13
  import { applyTemplates } from '../template/template-helpers.js';
14
- import { getCurrentEditor, createMemFsEditor } from '../utils/fs-adapter.js';
15
14
  /**
16
15
  * Copy adaptation (extension) project files from templates
17
16
  *
17
+ * @param fs - mem-fs-editor instance for file operations
18
18
  * @param projectInfo - Project import information
19
19
  * @param snapshotUrl - URL for UI5 snapshot version
20
- * @param fs - mem-fs-editor instance for file operations
21
20
  * @returns Result object with fs editor, success status and messages
22
21
  */
23
- export async function copyAdaptationFiles(projectInfo, snapshotUrl, fs) {
22
+ export async function copyAdaptationFiles(fs, projectInfo, snapshotUrl) {
24
23
  const messages = [];
25
24
  const { moduleName, moduleDescription, ui5Version, appTitle, rootPath, destination } = projectInfo;
26
25
  let result;
27
- let updatedFs;
28
26
  try {
29
27
  const projectUI5Version = getUI5Version(ui5Version || ''); // Defaults to '' if latest
30
28
  const adpConfig = {
@@ -63,8 +61,8 @@ export async function copyAdaptationFiles(projectInfo, snapshotUrl, fs) {
63
61
  fioriTools: true
64
62
  }
65
63
  };
66
- updatedFs = await migrate(rootPath, adpConfig);
67
- // NOTE: Caller is responsible for committing changes
64
+ // Write into the shared editor; caller commits the changes.
65
+ await migrate(rootPath, adpConfig, fs);
68
66
  result = messages.length === 0;
69
67
  }
70
68
  catch (e) {
@@ -74,24 +72,21 @@ export async function copyAdaptationFiles(projectInfo, snapshotUrl, fs) {
74
72
  description: `Error copying adaptation files: ${determineMessage(e)}`
75
73
  });
76
74
  result = false;
77
- updatedFs = fs || (await import('../utils/fs-adapter.js')).createMemFsEditor();
78
75
  }
79
- return { fs: updatedFs, result, messages };
76
+ return { fs, result, messages };
80
77
  }
81
78
  /**
82
79
  * Copy library project files from templates
83
80
  *
81
+ * @param fs - mem-fs editor
84
82
  * @param projectInfo - Project import information
85
83
  * @returns Result object with fs editor, success status and messages
86
84
  */
87
- export async function copyLibraryFiles(projectInfo) {
85
+ export async function copyLibraryFiles(fs, projectInfo) {
88
86
  const messages = [];
89
87
  const { moduleName, rootPath } = projectInfo;
90
88
  let result;
91
- let fs;
92
89
  try {
93
- // Get fs from context or create new one
94
- fs = getCurrentEditor() || createMemFsEditor();
95
90
  const deps = { ...devDependencies };
96
91
  delete deps.rimraf;
97
92
  const packageJson = {
@@ -113,12 +108,12 @@ export async function copyLibraryFiles(projectInfo) {
113
108
  };
114
109
  // Perform migration for Reuse Library
115
110
  // 1. Create app settings (package.json)
116
- await applyTemplates(getLibraryTemplatesMap(), templateData, rootPath, TemplateFileName.LibrarySettings);
111
+ await applyTemplates(fs, getLibraryTemplatesMap(), templateData, rootPath, TemplateFileName.LibrarySettings);
117
112
  //2. Create ui5.yaml
118
- const ui5YamlTemplate = readFile(join(templatesDirPath, TemplateFileName.LibrarySettings, TemplateFileName.UI5Yaml));
113
+ const ui5YamlTemplate = readFile(fs, join(templatesDirPath, TemplateFileName.LibrarySettings, TemplateFileName.UI5Yaml));
119
114
  const ui5YamlContent = render(ui5YamlTemplate, templateData.ui5Yaml, { escape: escapeXML });
120
115
  const ui5YamlJson = parse(ui5YamlContent);
121
- updateFile(join(rootPath, TemplateFileName.UI5Yaml), stringify(ui5YamlJson));
116
+ updateFile(fs, join(rootPath, TemplateFileName.UI5Yaml), stringify(ui5YamlJson));
122
117
  result = messages.length === 0;
123
118
  }
124
119
  catch (e) {
@@ -130,7 +125,6 @@ export async function copyLibraryFiles(projectInfo) {
130
125
  description: `Error copying library files: ${errorDetail}`
131
126
  });
132
127
  result = false;
133
- fs = createMemFsEditor();
134
128
  }
135
129
  return { fs, result, messages };
136
130
  }
@@ -1,21 +1,24 @@
1
1
  /**
2
2
  * Helper functions for creating and managing webapp folder structure
3
3
  */
4
+ import type { Editor } from 'mem-fs-editor';
4
5
  import type { ImportProjectInfo } from '../types.js';
5
6
  /**
6
7
  * Create basic extension project manifest.json
7
8
  * Creates a minimal manifest needed for extension project preview
8
9
  *
10
+ * @param fs
9
11
  * @param rootPath
10
12
  * @param projectInfo
11
13
  */
12
- export declare function createExtensionProjectManifest(rootPath: string, projectInfo: ImportProjectInfo): Promise<void>;
14
+ export declare function createExtensionProjectManifest(fs: Editor, rootPath: string, projectInfo: ImportProjectInfo): void;
13
15
  /**
14
16
  * Create webapp folder and migrate files into it
15
17
  * For projects with manifest.json at root level, creates webapp folder and moves appropriate files
16
18
  *
19
+ * @param fs
17
20
  * @param rootPath
18
21
  * @param projectInfo
19
22
  */
20
- export declare function createWebappFolderAndMigrateFiles(rootPath: string, projectInfo: ImportProjectInfo): Promise<void>;
23
+ export declare function createWebappFolderAndMigrateFiles(fs: Editor, rootPath: string, projectInfo: ImportProjectInfo): Promise<void>;
21
24
  //# sourceMappingURL=webapp.d.ts.map
@@ -6,7 +6,7 @@ import { stat, readdir, access } from 'node:fs/promises';
6
6
  import { fileExists, updateJSON, readFile, writeFile, deleteFile } from '../utils/index.js';
7
7
  import { DirName, FileName } from '../project-spec-types.js';
8
8
  import { CommandRunner } from '@sap-ux/nodejs-utils';
9
- import { mkdir, exists, isMemFsEnabled, getCurrentEditor } from '../utils/fs-adapter.js';
9
+ import { editorHasPath } from '../utils/fs-adapter.js';
10
10
  import { MigrationTypes } from '../utils/constants.js';
11
11
  import { validateRootDirectory, validateGitRelativePath } from '../utils/path-validation.js';
12
12
  import { hasStore } from '../types/mem-fs-types.js';
@@ -27,11 +27,12 @@ async function pathExistsOnDisk(path) {
27
27
  /**
28
28
  * Move files using git and fallback to filesystem move
29
29
  *
30
+ * @param fs - mem-fs editor
30
31
  * @param rootPath - Project root path
31
32
  * @param dirContent - Directory entries to process
32
33
  * @param direntToFilter - Files/directories to exclude
33
34
  */
34
- async function moveFilesWithGitFallback(rootPath, dirContent, direntToFilter) {
35
+ async function moveFilesWithGitFallback(fs, rootPath, dirContent, direntToFilter) {
35
36
  const runner = new CommandRunner();
36
37
  const safeRootPath = await validateRootDirectory(rootPath);
37
38
  // Move files sequentially to avoid git/filesystem race conditions
@@ -52,7 +53,7 @@ async function moveFilesWithGitFallback(rootPath, dirContent, direntToFilter) {
52
53
  // NOSONAR - Sequential check after git required
53
54
  const sourcePath = join(rootPath, entry.name);
54
55
  const destPath = join(rootPath, DirName.Webapp, entry.name);
55
- await recursiveMove(sourcePath, destPath); // NOSONAR - Filesystem race prevention
56
+ await recursiveMove(fs, sourcePath, destPath); // NOSONAR - Filesystem race prevention
56
57
  }
57
58
  }
58
59
  }
@@ -61,12 +62,13 @@ async function moveFilesWithGitFallback(rootPath, dirContent, direntToFilter) {
61
62
  * Recursively move files and directories from source to destination
62
63
  * Handles both mem-fs and real filesystem operations
63
64
  *
65
+ * @param fs - mem-fs editor
64
66
  * @param sourcePath - Source path
65
67
  * @param destPath - Destination path
66
68
  */
67
- async function recursiveMove(sourcePath, destPath) {
68
- // Check if source exists (handles both mem-fs and real fs)
69
- if (!(await exists(sourcePath)) && !(await pathExistsOnDisk(sourcePath))) {
69
+ async function recursiveMove(fs, sourcePath, destPath) {
70
+ // Check if source exists (staged in mem-fs or on the real filesystem)
71
+ if (!editorHasPath(fs, sourcePath) && !(await pathExistsOnDisk(sourcePath))) {
70
72
  return; // Nothing to move
71
73
  }
72
74
  // Check if it's a directory (real fs check - mem-fs doesn't have directories)
@@ -76,41 +78,35 @@ async function recursiveMove(sourcePath, destPath) {
76
78
  isDirectory = stats.isDirectory();
77
79
  }
78
80
  if (isDirectory) {
79
- // Ensure destination directory exists
80
- mkdir(destPath);
81
- // Read directory contents (real fs)
81
+ // Read directory contents (real fs); mem-fs creates directories implicitly on write
82
82
  const entries = await readdir(sourcePath, { withFileTypes: true });
83
83
  // Recursively move each entry sequentially to maintain filesystem consistency
84
84
  for (const entry of entries) {
85
85
  const srcEntry = join(sourcePath, entry.name);
86
86
  const destEntry = join(destPath, entry.name);
87
- await recursiveMove(srcEntry, destEntry); // NOSONAR: Parent-child order preservation required
88
- }
89
- // Delete the now-empty source directory (real fs only)
90
- if (!isMemFsEnabled() && (await pathExistsOnDisk(sourcePath))) {
91
- const { rm } = await import('node:fs/promises');
92
- await rm(sourcePath, { recursive: true, force: true });
87
+ await recursiveMove(fs, srcEntry, destEntry); // NOSONAR: Parent-child order preservation required
93
88
  }
94
89
  }
95
90
  else {
96
91
  // It's a file - copy it
97
- const content = readFile(sourcePath);
98
- writeFile(destPath, content);
92
+ const content = readFile(fs, sourcePath);
93
+ writeFile(fs, destPath, content);
99
94
  // Delete source file after copying
100
- deleteFile(sourcePath);
95
+ deleteFile(fs, sourcePath);
101
96
  }
102
97
  }
103
98
  /**
104
99
  * Create basic extension project manifest.json
105
100
  * Creates a minimal manifest needed for extension project preview
106
101
  *
102
+ * @param fs
107
103
  * @param rootPath
108
104
  * @param projectInfo
109
105
  */
110
- export async function createExtensionProjectManifest(rootPath, projectInfo) {
106
+ export function createExtensionProjectManifest(fs, rootPath, projectInfo) {
111
107
  // Only create if manifest doesn't exist and it's an extension project
112
- if (!(await fileExists(join(rootPath, projectInfo.webappPath, FileName.Manifest))) &&
113
- !(await fileExists(join(rootPath, FileName.Manifest))) &&
108
+ if (!fileExists(fs, join(rootPath, projectInfo.webappPath, FileName.Manifest)) &&
109
+ !fileExists(fs, join(rootPath, FileName.Manifest)) &&
114
110
  projectInfo.type === MigrationTypes.projectExtension) {
115
111
  // Add a basic manifest.json (not linked in component.json) needed for preview
116
112
  const manifestJson = {
@@ -149,13 +145,13 @@ export async function createExtensionProjectManifest(rootPath, projectInfo) {
149
145
  }
150
146
  };
151
147
  // Write manifest to appropriate location
152
- // Check if webapp directory exists (works for both mem-fs and real fs)
153
- const shouldWriteToWebapp = projectInfo.webappPath && (await exists(join(rootPath, projectInfo.webappPath)));
148
+ // Check if webapp directory exists (staged in mem-fs or on disk, including an empty real dir)
149
+ const shouldWriteToWebapp = projectInfo.webappPath && fileExists(fs, join(rootPath, projectInfo.webappPath));
154
150
  if (shouldWriteToWebapp) {
155
- updateJSON(join(rootPath, projectInfo.webappPath, FileName.Manifest), manifestJson);
151
+ updateJSON(fs, join(rootPath, projectInfo.webappPath, FileName.Manifest), manifestJson);
156
152
  }
157
153
  else {
158
- updateJSON(join(rootPath, FileName.Manifest), manifestJson);
154
+ updateJSON(fs, join(rootPath, FileName.Manifest), manifestJson);
159
155
  projectInfo.webappPath = '';
160
156
  }
161
157
  }
@@ -164,18 +160,18 @@ export async function createExtensionProjectManifest(rootPath, projectInfo) {
164
160
  * Create webapp folder and migrate files into it
165
161
  * For projects with manifest.json at root level, creates webapp folder and moves appropriate files
166
162
  *
163
+ * @param fs
167
164
  * @param rootPath
168
165
  * @param projectInfo
169
166
  */
170
- export async function createWebappFolderAndMigrateFiles(rootPath, projectInfo) {
167
+ export async function createWebappFolderAndMigrateFiles(fs, rootPath, projectInfo) {
171
168
  // Only proceed if webapp path is empty and manifest exists in root
172
169
  const manifestPath = join(rootPath, FileName.Manifest);
173
- const manifestExists = await fileExists(manifestPath);
170
+ const manifestExists = fileExists(fs, manifestPath);
174
171
  if (projectInfo.webappPath === '' && manifestExists) {
175
172
  // manifest.json is outside of webapp folder and should not be a legacy project
176
173
  // as previous block will have updated this folder structure
177
174
  // create webapp, move files into it and update current webapp path
178
- mkdir(join(rootPath, DirName.Webapp));
179
175
  // List of files/directories to exclude from migration
180
176
  const direntToFilter = [
181
177
  'neo-app.json',
@@ -194,15 +190,14 @@ export async function createWebappFolderAndMigrateFiles(rootPath, projectInfo) {
194
190
  '.eslintrc',
195
191
  '.eslintrc.ext'
196
192
  ];
197
- const editor = getCurrentEditor();
198
- if (editor && hasStore(editor)) {
193
+ if (hasStore(fs)) {
199
194
  // Use mem-fs to get directory listing
200
195
  // mem-fs stores keys with forward slashes, so normalize separators for Windows compatibility
201
196
  const normalizedRoot = rootPath.replaceAll('\\', '/');
202
197
  const rootPathWithSep = normalizedRoot.endsWith('/') ? normalizedRoot : normalizedRoot + '/';
203
198
  const filesToMove = [];
204
199
  // Collect all files under root, excluding those whose top-level segment is filtered
205
- editor.store.each((file) => {
200
+ fs.store.each((file) => {
206
201
  const filePath = file.path.replaceAll('\\', '/'); // Normalize mem-fs keys
207
202
  if (filePath.startsWith(rootPathWithSep)) {
208
203
  const relativePath = filePath.substring(rootPathWithSep.length);
@@ -219,15 +214,15 @@ export async function createWebappFolderAndMigrateFiles(rootPath, projectInfo) {
219
214
  const normalizedPath = filePath.replaceAll('\\', '/');
220
215
  const relativePath = normalizedPath.substring(rootPathWithSep.length);
221
216
  const destPath = join(rootPath, DirName.Webapp, relativePath);
222
- const content = readFile(filePath);
223
- writeFile(destPath, content);
224
- deleteFile(filePath);
217
+ const content = readFile(fs, filePath);
218
+ writeFile(fs, destPath, content);
219
+ deleteFile(fs, filePath);
225
220
  }
226
221
  }
227
222
  else {
228
223
  // Use real filesystem - extracted to helper for reduced complexity
229
224
  const dirContent = await readdir(rootPath, { withFileTypes: true });
230
- await moveFilesWithGitFallback(rootPath, dirContent, direntToFilter);
225
+ await moveFilesWithGitFallback(fs, rootPath, dirContent, direntToFilter);
231
226
  }
232
227
  // Update webapp path
233
228
  projectInfo.webappPath = DirName.Webapp;
package/dist/index.d.ts CHANGED
@@ -45,12 +45,12 @@ export { BulkProjectMigrator } from './BulkProjectMigrator.js';
45
45
  export { createMemFsEditor } from './utils/fs-adapter.js';
46
46
  export * from './types.js';
47
47
  export * from './i18n.js';
48
- export { findProjectRoot, getProjectType, getMainService, hasDependency, getMinUI5VersionAsArray, type CdsUi5PluginInfo, readFile, readJSON, fileExists, writeFile, updateFile, updateJSON, deleteFile, findAllManifest, isFioriToolsProject, determineMessage } from './utils/index.js';
48
+ export { readFile, findProjectRoot, getProjectType, getMainService, hasDependency, getMinUI5VersionAsArray, type CdsUi5PluginInfo, readJSON, fileExists, writeFile, updateFile, updateJSON, deleteFile, findAllManifest, isFioriToolsProject, determineMessage } from './utils/index.js';
49
49
  export { buildMainBackend, buildProxyConfig, buildPreviewMiddleware } from './adapters/ui5-config-helpers.js';
50
50
  export { generateUI5YamlContent, generateUI5LocalYamlContent, generateUI5MockYamlContent } from './adapters/ui5-config-adapter.js';
51
51
  export type { UI5YamlOptions } from './adapters/ui5-config-adapter.js';
52
52
  export { readManifest, getUI5Version } from './utils/manifest-and-version-utils.js';
53
- export { stripSpaces, escapeSingleQuotes, escapeDoubleQuotes, doesDirectoryExists } from './utils/file-system-utils.js';
53
+ export { stripSpaces, escapeSingleQuotes, escapeDoubleQuotes, doesDirectoryExists, createDirectory, doesPropertyExist } from './utils/file-system-utils.js';
54
54
  export { generateSapLibsStr, getSourceTemplate } from './utils/migration-utils.js';
55
55
  export { getWebIDEProjectPathsAsLabels } from './utils/project-discovery.js';
56
56
  export { handleGitIgnoreFile, handlePackageJsonFile, handleLocateReuseLibsFile } from './utils/template-generators/index.js';
package/dist/index.js CHANGED
@@ -54,7 +54,7 @@ export * from './types.js';
54
54
  // Public API - i18n
55
55
  export * from './i18n.js';
56
56
  // Public API - Utilities (re-export selective functions for backward compatibility)
57
- export { findProjectRoot, getProjectType, getMainService, hasDependency, getMinUI5VersionAsArray, readFile, readJSON, fileExists, writeFile, updateFile, updateJSON, deleteFile, findAllManifest, isFioriToolsProject,
57
+ export { readFile, findProjectRoot, getProjectType, getMainService, hasDependency, getMinUI5VersionAsArray, readJSON, fileExists, writeFile, updateFile, updateJSON, deleteFile, findAllManifest, isFioriToolsProject,
58
58
  // Additional exports for test compatibility
59
59
  determineMessage } from './utils/index.js';
60
60
  // Additional exports from adapters for test compatibility
@@ -62,7 +62,7 @@ export { buildMainBackend, buildProxyConfig, buildPreviewMiddleware } from './ad
62
62
  export { generateUI5YamlContent, generateUI5LocalYamlContent, generateUI5MockYamlContent } from './adapters/ui5-config-adapter.js';
63
63
  // Additional exports from utils for test compatibility
64
64
  export { readManifest, getUI5Version } from './utils/manifest-and-version-utils.js';
65
- export { stripSpaces, escapeSingleQuotes, escapeDoubleQuotes, doesDirectoryExists } from './utils/file-system-utils.js';
65
+ export { stripSpaces, escapeSingleQuotes, escapeDoubleQuotes, doesDirectoryExists, createDirectory, doesPropertyExist } from './utils/file-system-utils.js';
66
66
  export { generateSapLibsStr, getSourceTemplate } from './utils/migration-utils.js';
67
67
  export { getWebIDEProjectPathsAsLabels } from './utils/project-discovery.js';
68
68
  export { handleGitIgnoreFile, handlePackageJsonFile, handleLocateReuseLibsFile } from './utils/template-generators/index.js';
@@ -2,6 +2,7 @@
2
2
  * Helper functions for preparing configuration data during migration
3
3
  */
4
4
  import type { ImportProjectInfo } from '../types.js';
5
+ import type { Editor } from 'mem-fs-editor';
5
6
  /**
6
7
  * Configuration data prepared for migration
7
8
  */
@@ -22,10 +23,11 @@ export interface PreparedConfigurationData {
22
23
  * Prepare all configuration data needed for migration
23
24
  * Consolidates theme resolution, component mapping, and project/service data preparation
24
25
  *
26
+ * @param fs - mem-fs editor
25
27
  * @param projectInfo - Project information
26
28
  * @param ui5Version - UI5 version (can be undefined)
27
29
  * @param enableTypeScript - Whether TypeScript support should be enabled
28
30
  * @returns Prepared configuration data
29
31
  */
30
- export declare function prepareConfigurationData(projectInfo: ImportProjectInfo, ui5Version: string | undefined, enableTypeScript?: boolean): Promise<PreparedConfigurationData>;
32
+ export declare function prepareConfigurationData(fs: Editor, projectInfo: ImportProjectInfo, ui5Version: string | undefined, enableTypeScript?: boolean): Promise<PreparedConfigurationData>;
31
33
  //# sourceMappingURL=configuration.d.ts.map
@@ -6,14 +6,15 @@ import { prepareProjectAndServiceData } from '../project/project-data.js';
6
6
  * Prepare all configuration data needed for migration
7
7
  * Consolidates theme resolution, component mapping, and project/service data preparation
8
8
  *
9
+ * @param fs - mem-fs editor
9
10
  * @param projectInfo - Project information
10
11
  * @param ui5Version - UI5 version (can be undefined)
11
12
  * @param enableTypeScript - Whether TypeScript support should be enabled
12
13
  * @returns Prepared configuration data
13
14
  */
14
- export async function prepareConfigurationData(projectInfo, ui5Version, enableTypeScript = false) {
15
+ export async function prepareConfigurationData(fs, projectInfo, ui5Version, enableTypeScript = false) {
15
16
  // Get supported themes for the project
16
- const supportedThemes = await getSupportedThemes(projectInfo, ui5Version || '');
17
+ const supportedThemes = await getSupportedThemes(fs, projectInfo, ui5Version || '');
17
18
  const ui5Theme = getUi5ThemeBasedOnUi5Version(ui5Version ?? '', projectInfo.ui5Theme);
18
19
  // Get component mapping based on floor plan
19
20
  const { appMigratorSrcComponentToReplace, semanticObject } = getComponentMapping(projectInfo);
@@ -1,3 +1,4 @@
1
+ import type { Editor } from 'mem-fs-editor';
1
2
  export { validateRootDirectory } from '../utils/path-validation.js';
2
3
  /**
3
4
  * Build legacy folder paths for migration
@@ -21,10 +22,11 @@ export declare function buildLegacyPaths(rootPath: string, legacyPath: string):
21
22
  * Try to move folders using git to preserve history
22
23
  * Uses relative paths from validated root directory to prevent command injection
23
24
  *
25
+ * @param fs - mem-fs editor
24
26
  * @param rootPath - Project root path
25
27
  * @param _paths - Legacy paths object (unused, paths rebuilt internally for security)
26
28
  */
27
- export declare function tryGitMove(rootPath: string, _paths: LegacyPaths): Promise<void>;
29
+ export declare function tryGitMove(fs: Editor, rootPath: string, _paths: LegacyPaths): Promise<void>;
28
30
  /**
29
31
  * Fallback folder move using node fs
30
32
  *
@@ -3,9 +3,9 @@ import { access, readdir } from 'node:fs/promises';
3
3
  import { CommandRunner } from '@sap-ux/nodejs-utils';
4
4
  import { DirName } from '../project-spec-types.js';
5
5
  import { TemplateFileName } from '../index.js';
6
- import { isMemFsEnabled, getCurrentEditor, exists } from '../utils/fs-adapter.js';
7
6
  import { validateRootDirectory, validateGitRelativePath } from '../utils/path-validation.js';
8
7
  import { hasStore } from '../types/mem-fs-types.js';
8
+ import { editorHasPath } from '../utils/fs-adapter.js';
9
9
  // Re-export for backward compatibility with tests
10
10
  export { validateRootDirectory } from '../utils/path-validation.js';
11
11
  /**
@@ -57,21 +57,21 @@ function moveMemFsDirectory(fs, fromPath, toPath) {
57
57
  fs.delete(oldPath);
58
58
  }
59
59
  }
60
- async function memFsMove(rootPath, paths) {
61
- const editor = getCurrentEditor();
62
- if (!editor || !hasStore(editor)) {
60
+ function memFsMove(fs, rootPath, paths) {
61
+ if (!hasStore(fs)) {
63
62
  return;
64
63
  }
64
+ const editor = fs;
65
65
  // Move webapp files from src/main/webapp to webapp
66
- if (await exists(paths.ffLegacyWebappPath)) {
66
+ if (editorHasPath(fs, paths.ffLegacyWebappPath)) {
67
67
  moveMemFsDirectory(editor, paths.ffLegacyWebappPath, join(rootPath, DirName.Webapp));
68
68
  }
69
- // Move test/qunit to webapp/test/qunit
70
- if (await exists(paths.ffLegacyTestQunitPath)) {
71
- moveMemFsDirectory(editor, paths.ffLegacyTestQunitPath, join(paths.ffNewTestPath, 'qunit'));
69
+ // Move test/qunit to webapp/test (replacing the test path, not nesting under qunit)
70
+ if (editorHasPath(fs, paths.ffLegacyTestQunitPath)) {
71
+ moveMemFsDirectory(editor, paths.ffLegacyTestQunitPath, paths.ffNewTestPath);
72
72
  }
73
73
  // Move test/uiveri5 to webapp/test/uiveri5
74
- if (await exists(paths.ffLegacyTestuiveri5Path)) {
74
+ if (editorHasPath(fs, paths.ffLegacyTestuiveri5Path)) {
75
75
  moveMemFsDirectory(editor, paths.ffLegacyTestuiveri5Path, join(paths.ffNewTestPath, 'uiveri5'));
76
76
  }
77
77
  }
@@ -93,15 +93,13 @@ async function pathExistsOnDisk(path) {
93
93
  * Try to move folders using git to preserve history
94
94
  * Uses relative paths from validated root directory to prevent command injection
95
95
  *
96
+ * @param fs - mem-fs editor
96
97
  * @param rootPath - Project root path
97
98
  * @param _paths - Legacy paths object (unused, paths rebuilt internally for security)
98
99
  */
99
- export async function tryGitMove(rootPath, _paths) {
100
- // In mem-fs mode, use mem-fs operations instead of git
101
- if (isMemFsEnabled()) {
102
- await memFsMove(rootPath, _paths);
103
- return;
104
- }
100
+ export async function tryGitMove(fs, rootPath, _paths) {
101
+ // Keep the in-memory store consistent by moving the staged files first.
102
+ memFsMove(fs, rootPath, _paths);
105
103
  const runner = new CommandRunner();
106
104
  try {
107
105
  // Validate root directory - this is the only absolute path passed to git (-C option)
@@ -144,24 +142,18 @@ export async function tryGitMove(rootPath, _paths) {
144
142
  * @param paths - Legacy paths object
145
143
  */
146
144
  export async function fallbackFsMove(rootPath, paths) {
147
- // Note: In mem-fs mode, file moves are handled by git (preferred path)
148
- // This fallback only works for real file system operations
149
- // Mem-fs doesn't support atomic moves, so this is intentionally a no-op in mem-fs mode
150
- if (isMemFsEnabled()) {
151
- // Skip fallback in mem-fs mode - files should have been moved by git
152
- return;
153
- }
154
- // Real file system fallback
155
- // Use filesystem operations for cleanup
145
+ // Real file system fallback - always runs to clean up legacy structure from disk.
146
+ // In mem-fs mode the new files are already staged in the editor; the real moves here
147
+ // delete the old source directories so they are absent after editor.commit().
156
148
  const { default: fse } = await import('fs-extra');
157
149
  if (await pathExistsOnDisk(paths.ffLegacyWebappPath)) {
158
- fse.moveSync(paths.ffLegacyWebappPath, join(rootPath, DirName.Webapp));
150
+ fse.moveSync(paths.ffLegacyWebappPath, join(rootPath, DirName.Webapp), { overwrite: true });
159
151
  }
160
152
  if (await pathExistsOnDisk(paths.ffLegacyTestQunitPath)) {
161
- fse.moveSync(paths.ffLegacyTestQunitPath, paths.ffNewTestPath);
153
+ fse.moveSync(paths.ffLegacyTestQunitPath, paths.ffNewTestPath, { overwrite: true });
162
154
  }
163
155
  if (await pathExistsOnDisk(paths.ffLegacyTestuiveri5Path)) {
164
- fse.moveSync(paths.ffLegacyTestuiveri5Path, paths.ffNewTestPath);
156
+ fse.moveSync(paths.ffLegacyTestuiveri5Path, join(paths.ffNewTestPath, 'uiveri5'), { overwrite: true });
165
157
  }
166
158
  }
167
159
  /**
@@ -172,11 +164,6 @@ export async function fallbackFsMove(rootPath, paths) {
172
164
  * @param paths - Legacy paths object
173
165
  */
174
166
  export async function cleanupEmptyDirs(rootPath, legacyPath, paths) {
175
- // Note: In mem-fs mode, directory removal isn't needed
176
- // Mem-fs only tracks files, not empty directories
177
- if (isMemFsEnabled()) {
178
- return;
179
- }
180
167
  const fsextra = await import('fs-extra');
181
168
  const dirsToRemove = [join(rootPath, legacyPath), paths.ffLegacyTestPath, join(rootPath, 'src')];
182
169
  // Check and remove directories sequentially to avoid filesystem race conditions
@@ -2,15 +2,17 @@
2
2
  * Helper functions for migrating legacy Fiori Elements folder structures
3
3
  * Handles migration from /src/main/webapp to /webapp structure
4
4
  */
5
+ import type { Editor } from 'mem-fs-editor';
5
6
  import type { ImportProjectInfo } from '../types.js';
6
7
  /**
7
8
  * Migrate project from legacy Fiori Elements folder structure (/src/main/webapp) to new structure (/webapp)
8
9
  *
10
+ * @param fs - mem-fs editor
9
11
  * @param projectInfo - Project information including current webapp path
10
12
  * @param rootPath - Root path of the project
11
13
  * @returns Object containing updated keepIndex flag and updated webapp path
12
14
  */
13
- export declare function migrateLegacyFolderStructure(projectInfo: ImportProjectInfo, rootPath: string): Promise<{
15
+ export declare function migrateLegacyFolderStructure(fs: Editor, projectInfo: ImportProjectInfo, rootPath: string): Promise<{
14
16
  keepIndex: boolean;
15
17
  webappPath: string;
16
18
  }>;