@magentrix-corp/magentrix-cli 1.1.0 → 1.1.2

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.
@@ -165,9 +165,29 @@ const handleCreateStaticAssetAction = async (instanceUrl, apiKey, action) => {
165
165
  * Handles DELETE_STATIC_ASSET action.
166
166
  */
167
167
  const handleDeleteStaticAssetAction = async (instanceUrl, apiKey, action) => {
168
- const response = await deleteAsset(instanceUrl, apiKey, `/${action.folder}`, action.names);
169
- if (response?.error) throw new Error(response.error);
170
- return response;
168
+ try {
169
+ const response = await deleteAsset(instanceUrl, apiKey, `/${action.folder}`, action.names);
170
+ return response;
171
+ } catch (error) {
172
+ // Check if this is a "not found" error
173
+ const errorMessage = error?.message || String(error);
174
+ const errorLower = errorMessage.toLowerCase();
175
+ const isNotFound = errorLower.includes('404') ||
176
+ errorLower.includes('not found') ||
177
+ errorLower.includes('item not found');
178
+
179
+ if (isNotFound) {
180
+ // Clean up base.json since file doesn't exist on server
181
+ for (const name of action.names) {
182
+ const filePath = action.filePath || `${EXPORT_ROOT}/${action.folder}/${name}`;
183
+ removeFromBase(filePath);
184
+ }
185
+ return { cleanedFromCache: true };
186
+ }
187
+
188
+ // Other errors should still fail
189
+ throw error;
190
+ }
171
191
  };
172
192
 
173
193
  /**
@@ -183,9 +203,44 @@ const handleCreateFolderAction = async (instanceUrl, apiKey, action) => {
183
203
  * Handles DELETE_FOLDER action.
184
204
  */
185
205
  const handleDeleteFolderAction = async (instanceUrl, apiKey, action) => {
186
- const response = await deleteAsset(instanceUrl, apiKey, action.parentPath, [action.folderName]);
187
- if (response?.error) throw new Error(response.error);
188
- return response;
206
+ try {
207
+ const response = await deleteAsset(instanceUrl, apiKey, action.parentPath, [action.folderName]);
208
+ return response;
209
+ } catch (error) {
210
+ // Check if this is a "not found" error
211
+ const errorMessage = error?.message || String(error);
212
+ const errorLower = errorMessage.toLowerCase();
213
+ const isNotFound = errorLower.includes('404') ||
214
+ errorLower.includes('not found') ||
215
+ errorLower.includes('item not found');
216
+
217
+ if (isNotFound) {
218
+ // Clean up base.json since folder doesn't exist on server
219
+ removeFromBase(action.folderPath);
220
+
221
+ // Also remove all files and subfolders inside this folder from base
222
+ const hits = await config.searchObject({}, { filename: "base.json", global: false });
223
+ const cachedResults = hits?.[0]?.value || {};
224
+
225
+ for (const [recordId, cachedEntry] of Object.entries(cachedResults)) {
226
+ const entryPath = cachedEntry.filePath || cachedEntry.lastKnownPath;
227
+ if (entryPath && typeof entryPath === 'string') {
228
+ const normalizedEntryPath = path.normalize(entryPath);
229
+ const normalizedFolderPath = path.normalize(action.folderPath);
230
+
231
+ // Check if this entry is inside the deleted folder
232
+ if (normalizedEntryPath.startsWith(normalizedFolderPath + path.sep)) {
233
+ removeFromBase(recordId);
234
+ }
235
+ }
236
+ }
237
+
238
+ return { cleanedFromCache: true };
239
+ }
240
+
241
+ // Other errors should still fail
242
+ throw error;
243
+ }
189
244
  };
190
245
 
191
246
  /**
@@ -227,8 +282,12 @@ const updateCacheAfterSuccess = async (action, operationResult) => {
227
282
  break;
228
283
 
229
284
  case "delete_static_asset":
230
- for (const name of action.names) {
231
- removeFromBase(`${EXPORT_ROOT}/${action.folder}/${name}`);
285
+ // Skip if already cleaned from cache during 404 handling
286
+ if (!operationResult?.cleanedFromCache) {
287
+ for (const name of action.names) {
288
+ const filePath = action.filePath || `${EXPORT_ROOT}/${action.folder}/${name}`;
289
+ removeFromBase(filePath);
290
+ }
232
291
  }
233
292
  break;
234
293
 
@@ -240,9 +299,31 @@ const updateCacheAfterSuccess = async (action, operationResult) => {
240
299
  updateBase(action.folderPath, { Id: action.folderPath, Type: "Folder" });
241
300
  break;
242
301
 
243
- case "delete_folder":
244
- removeFromBase(action.folderPath);
302
+ case "delete_folder": {
303
+ // Skip if already cleaned from cache during 404 handling
304
+ if (!operationResult?.cleanedFromCache) {
305
+ // Remove the folder itself from base
306
+ removeFromBase(action.folderPath);
307
+
308
+ // Also remove all files and subfolders inside this folder from base
309
+ const hits = await config.searchObject({}, { filename: "base.json", global: false });
310
+ const cachedResults = hits?.[0]?.value || {};
311
+
312
+ for (const [recordId, cachedEntry] of Object.entries(cachedResults)) {
313
+ const entryPath = cachedEntry.filePath || cachedEntry.lastKnownPath;
314
+ if (entryPath && typeof entryPath === 'string') {
315
+ const normalizedEntryPath = path.normalize(entryPath);
316
+ const normalizedFolderPath = path.normalize(action.folderPath);
317
+
318
+ // Check if this entry is inside the deleted folder
319
+ if (normalizedEntryPath.startsWith(normalizedFolderPath + path.sep)) {
320
+ removeFromBase(recordId);
321
+ }
322
+ }
323
+ }
324
+ }
245
325
  break;
326
+ }
246
327
  }
247
328
  } catch (error) {
248
329
  console.warn(chalk.yellow(`Warning: Failed to update cache for ${action.action}: ${error.message}`));
@@ -472,7 +553,8 @@ export const runPublish = async (options = {}) => {
472
553
  actionQueue.push({
473
554
  action: 'delete_static_asset',
474
555
  folder: toApiPath(cacheFile.filePath),
475
- names: [path.basename(cacheFile.filePath)]
556
+ names: [path.basename(cacheFile.filePath)],
557
+ filePath: cacheFile.filePath // Store actual file path for filtering
476
558
  });
477
559
  continue;
478
560
  }
@@ -578,10 +660,17 @@ export const runPublish = async (options = {}) => {
578
660
  .map(a => a.folderPath);
579
661
 
580
662
  const filteredActionQueue = actionQueue.filter(action => {
581
- if (action.action === 'delete_static_asset') {
582
- const fileFolder = path.join(EXPORT_ROOT, action.folder);
663
+ if (action.action === 'delete_static_asset' && action.filePath) {
664
+ // Check if this file's directory is inside any folder being deleted
665
+ const fileDir = path.dirname(action.filePath);
583
666
  for (const deletedFolder of foldersBeingDeleted) {
584
- if (fileFolder.startsWith(deletedFolder)) {
667
+ // Use path.normalize to handle trailing slashes and ensure proper comparison
668
+ const normalizedFileDir = path.normalize(fileDir);
669
+ const normalizedDeletedFolder = path.normalize(deletedFolder);
670
+
671
+ // Check if file is inside the deleted folder (or is the folder itself)
672
+ if (normalizedFileDir === normalizedDeletedFolder ||
673
+ normalizedFileDir.startsWith(normalizedDeletedFolder + path.sep)) {
585
674
  return false; // Skip - covered by folder deletion
586
675
  }
587
676
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@magentrix-corp/magentrix-cli",
3
- "version": "1.1.0",
3
+ "version": "1.1.2",
4
4
  "description": "CLI tool for synchronizing local files with Magentrix cloud platform",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -80,7 +80,7 @@ export const deleteAsset = async (instanceUrl, token, path = '/contents/assets',
80
80
  if (!path) throw new Error("Path is required when deleting assets.");
81
81
  if (!Array.isArray(names) || names?.length === 0) throw new Error("At least one file name is required when deleting static assets.");
82
82
 
83
- let reqPath = `/api/3.0/staticassets?path=${encodeURIComponent(path)}&names=${names.join(",")}`;
83
+ let reqPath = `/api/3.0/staticassets?path=${encodeURIComponent(path)}&names=${names.map(name => encodeURIComponent(name)).join(",")}`;
84
84
 
85
85
  const response = await fetchMagentrix({
86
86
  instanceUrl,
package/vars/config.js CHANGED
@@ -1 +1,12 @@
1
- export const VERSION = '1.0.0'
1
+ import { readFileSync } from 'fs';
2
+ import { fileURLToPath } from 'url';
3
+ import { dirname, join } from 'path';
4
+
5
+ const __filename = fileURLToPath(import.meta.url);
6
+ const __dirname = dirname(__filename);
7
+
8
+ // Read version from package.json
9
+ const packageJsonPath = join(__dirname, '..', 'package.json');
10
+ const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf8'));
11
+
12
+ export const VERSION = packageJson.version;