@magentrix-corp/magentrix-cli 1.1.2 → 1.1.4
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/actions/publish.js +38 -7
- package/package.json +1 -1
- package/utils/assetPaths.js +14 -14
package/actions/publish.js
CHANGED
|
@@ -194,9 +194,25 @@ const handleDeleteStaticAssetAction = async (instanceUrl, apiKey, action) => {
|
|
|
194
194
|
* Handles CREATE_FOLDER action.
|
|
195
195
|
*/
|
|
196
196
|
const handleCreateFolderAction = async (instanceUrl, apiKey, action) => {
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
197
|
+
try {
|
|
198
|
+
const response = await createFolder(instanceUrl, apiKey, action.parentPath, action.folderName);
|
|
199
|
+
return response;
|
|
200
|
+
} catch (error) {
|
|
201
|
+
// Check if folder already exists (likely created by file upload)
|
|
202
|
+
const errorMessage = error?.message || String(error);
|
|
203
|
+
const errorLower = errorMessage.toLowerCase();
|
|
204
|
+
const alreadyExists = errorLower.includes('already exists') ||
|
|
205
|
+
errorLower.includes('folder exists') ||
|
|
206
|
+
errorLower.includes('duplicate');
|
|
207
|
+
|
|
208
|
+
if (alreadyExists) {
|
|
209
|
+
// Folder already exists, update cache and treat as success
|
|
210
|
+
return { alreadyExisted: true };
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// Other errors should still fail
|
|
214
|
+
throw error;
|
|
215
|
+
}
|
|
200
216
|
};
|
|
201
217
|
|
|
202
218
|
/**
|
|
@@ -654,27 +670,42 @@ export const runPublish = async (options = {}) => {
|
|
|
654
670
|
});
|
|
655
671
|
}
|
|
656
672
|
|
|
657
|
-
// Step 9: Filter out redundant file deletions
|
|
673
|
+
// Step 9: Filter out redundant file and folder deletions
|
|
658
674
|
const foldersBeingDeleted = actionQueue
|
|
659
675
|
.filter(a => a.action === 'delete_folder')
|
|
660
676
|
.map(a => a.folderPath);
|
|
661
677
|
|
|
662
678
|
const filteredActionQueue = actionQueue.filter(action => {
|
|
679
|
+
// Filter out files inside folders being deleted
|
|
663
680
|
if (action.action === 'delete_static_asset' && action.filePath) {
|
|
664
|
-
// Check if this file's directory is inside any folder being deleted
|
|
665
681
|
const fileDir = path.dirname(action.filePath);
|
|
666
682
|
for (const deletedFolder of foldersBeingDeleted) {
|
|
667
|
-
// Use path.normalize to handle trailing slashes and ensure proper comparison
|
|
668
683
|
const normalizedFileDir = path.normalize(fileDir);
|
|
669
684
|
const normalizedDeletedFolder = path.normalize(deletedFolder);
|
|
670
685
|
|
|
671
|
-
// Check if file is inside the deleted folder (or is the folder itself)
|
|
672
686
|
if (normalizedFileDir === normalizedDeletedFolder ||
|
|
673
687
|
normalizedFileDir.startsWith(normalizedDeletedFolder + path.sep)) {
|
|
674
688
|
return false; // Skip - covered by folder deletion
|
|
675
689
|
}
|
|
676
690
|
}
|
|
677
691
|
}
|
|
692
|
+
|
|
693
|
+
// Filter out child folders inside folders being deleted
|
|
694
|
+
if (action.action === 'delete_folder' && action.folderPath) {
|
|
695
|
+
for (const deletedFolder of foldersBeingDeleted) {
|
|
696
|
+
// Don't compare a folder to itself
|
|
697
|
+
if (action.folderPath === deletedFolder) continue;
|
|
698
|
+
|
|
699
|
+
const normalizedChildFolder = path.normalize(action.folderPath);
|
|
700
|
+
const normalizedParentFolder = path.normalize(deletedFolder);
|
|
701
|
+
|
|
702
|
+
// Check if this folder is inside another folder being deleted
|
|
703
|
+
if (normalizedChildFolder.startsWith(normalizedParentFolder + path.sep)) {
|
|
704
|
+
return false; // Skip - covered by parent folder deletion
|
|
705
|
+
}
|
|
706
|
+
}
|
|
707
|
+
}
|
|
708
|
+
|
|
678
709
|
return true;
|
|
679
710
|
});
|
|
680
711
|
|
package/package.json
CHANGED
package/utils/assetPaths.js
CHANGED
|
@@ -12,13 +12,13 @@ import { EXPORT_ROOT } from '../vars/global.js';
|
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
14
|
* Convert a local asset path to an API path by adding the 'contents' prefix
|
|
15
|
-
* and normalizing
|
|
15
|
+
* and normalizing with forward slashes (preserves original casing).
|
|
16
16
|
*
|
|
17
|
-
* @param {string} localPath - Local file path (e.g., "src/Assets/
|
|
18
|
-
* @returns {string} API path (e.g., "/contents/assets/
|
|
17
|
+
* @param {string} localPath - Local file path (e.g., "src/Assets/Images/Logo.png")
|
|
18
|
+
* @returns {string} API path (e.g., "/contents/assets/Images")
|
|
19
19
|
*
|
|
20
20
|
* @example
|
|
21
|
-
* toApiPath("src/Assets/
|
|
21
|
+
* toApiPath("src/Assets/Images/Logo.png") // "/contents/assets/Images"
|
|
22
22
|
* toApiPath("src/Assets") // "/contents/assets"
|
|
23
23
|
*/
|
|
24
24
|
export const toApiPath = (localPath) => {
|
|
@@ -31,11 +31,11 @@ export const toApiPath = (localPath) => {
|
|
|
31
31
|
const normalized = path.normalize(localPath);
|
|
32
32
|
const relative = normalized.replace(new RegExp(`^${EXPORT_ROOT}[\\\\/]?`), '');
|
|
33
33
|
|
|
34
|
-
// Replace 'Assets' with 'contents/assets'
|
|
34
|
+
// Replace 'Assets' with 'contents/assets' (case insensitive search, but replace with lowercase)
|
|
35
35
|
const apiPath = relative.replace(/^Assets/i, 'contents/assets');
|
|
36
36
|
|
|
37
|
-
// Normalize to forward slashes
|
|
38
|
-
let dirPath = path.dirname(apiPath).replace(/\\/g, '/')
|
|
37
|
+
// Normalize to forward slashes (preserve casing!), remove filename
|
|
38
|
+
let dirPath = path.dirname(apiPath).replace(/\\/g, '/');
|
|
39
39
|
|
|
40
40
|
// Handle edge case where dirname returns '.' for root
|
|
41
41
|
if (dirPath === '.') {
|
|
@@ -69,13 +69,13 @@ export const toLocalPath = (apiPath) => {
|
|
|
69
69
|
|
|
70
70
|
/**
|
|
71
71
|
* Convert a local folder path to an API path (keeps the folder, doesn't extract parent).
|
|
72
|
-
* Similar to toApiPath but for folders.
|
|
72
|
+
* Similar to toApiPath but for folders (preserves original casing).
|
|
73
73
|
*
|
|
74
|
-
* @param {string} localFolderPath - Local folder path (e.g., "src/Assets/
|
|
75
|
-
* @returns {string} API path (e.g., "/contents/assets/
|
|
74
|
+
* @param {string} localFolderPath - Local folder path (e.g., "src/Assets/Images")
|
|
75
|
+
* @returns {string} API path (e.g., "/contents/assets/Images")
|
|
76
76
|
*
|
|
77
77
|
* @example
|
|
78
|
-
* toApiFolderPath("src/Assets/
|
|
78
|
+
* toApiFolderPath("src/Assets/Images") // "/contents/assets/Images"
|
|
79
79
|
* toApiFolderPath("src/Assets") // "/contents/assets"
|
|
80
80
|
*/
|
|
81
81
|
export const toApiFolderPath = (localFolderPath) => {
|
|
@@ -88,11 +88,11 @@ export const toApiFolderPath = (localFolderPath) => {
|
|
|
88
88
|
const normalized = path.normalize(localFolderPath);
|
|
89
89
|
const relative = normalized.replace(new RegExp(`^${EXPORT_ROOT}[\\\\/]?`), '');
|
|
90
90
|
|
|
91
|
-
// Replace 'Assets' with 'contents/assets'
|
|
91
|
+
// Replace 'Assets' with 'contents/assets' (case insensitive search, but replace with lowercase)
|
|
92
92
|
let apiPath = relative.replace(/^Assets/i, 'contents/assets');
|
|
93
93
|
|
|
94
|
-
// Normalize to forward slashes
|
|
95
|
-
apiPath = apiPath.replace(/\\/g, '/')
|
|
94
|
+
// Normalize to forward slashes (preserve casing!)
|
|
95
|
+
apiPath = apiPath.replace(/\\/g, '/');
|
|
96
96
|
|
|
97
97
|
// Handle edge case where path is just 'Assets'
|
|
98
98
|
if (apiPath === 'contents/assets' || apiPath === '') {
|