farmon 0.1.0

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 (106) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +163 -0
  3. package/dist/bin/farmon.js +12 -0
  4. package/dist/bin/farmon.js.map +1 -0
  5. package/dist/execute/agents/index.js +19 -0
  6. package/dist/execute/agents/index.js.map +1 -0
  7. package/dist/execute/agents/instruction-classifier-agent.js +16 -0
  8. package/dist/execute/agents/instruction-classifier-agent.js.map +1 -0
  9. package/dist/execute/agents/mutation-agent.js +272 -0
  10. package/dist/execute/agents/mutation-agent.js.map +1 -0
  11. package/dist/execute/agents/query-agent.js +118 -0
  12. package/dist/execute/agents/query-agent.js.map +1 -0
  13. package/dist/execute/helpers/analyzers.js +8 -0
  14. package/dist/execute/helpers/analyzers.js.map +1 -0
  15. package/dist/execute/helpers/ensurers.js +1053 -0
  16. package/dist/execute/helpers/ensurers.js.map +1 -0
  17. package/dist/execute/helpers/finders.js +1454 -0
  18. package/dist/execute/helpers/finders.js.map +1 -0
  19. package/dist/execute/helpers/general.js +3736 -0
  20. package/dist/execute/helpers/general.js.map +1 -0
  21. package/dist/execute/helpers/import-helpers.js +183 -0
  22. package/dist/execute/helpers/import-helpers.js.map +1 -0
  23. package/dist/execute/helpers/parsers.js +840 -0
  24. package/dist/execute/helpers/parsers.js.map +1 -0
  25. package/dist/execute/helpers/prompt-maker.js +1163 -0
  26. package/dist/execute/helpers/prompt-maker.js.map +1 -0
  27. package/dist/execute/helpers/validators.js +40 -0
  28. package/dist/execute/helpers/validators.js.map +1 -0
  29. package/dist/execute/history/history-manager.js +1030 -0
  30. package/dist/execute/history/history-manager.js.map +1 -0
  31. package/dist/execute/history/rollback-handlers.js +2524 -0
  32. package/dist/execute/history/rollback-handlers.js.map +1 -0
  33. package/dist/execute/index.js +44 -0
  34. package/dist/execute/index.js.map +1 -0
  35. package/dist/execute/llm/call.js +103 -0
  36. package/dist/execute/llm/call.js.map +1 -0
  37. package/dist/execute/tasks/ast.js +3819 -0
  38. package/dist/execute/tasks/ast.js.map +1 -0
  39. package/dist/execute/tasks/generators.js +96 -0
  40. package/dist/execute/tasks/generators.js.map +1 -0
  41. package/dist/execute/tasks/index.js +7 -0
  42. package/dist/execute/tasks/index.js.map +1 -0
  43. package/dist/execute/tasks/mutations.js +8139 -0
  44. package/dist/execute/tasks/mutations.js.map +1 -0
  45. package/dist/execute/tasks/query.js +248 -0
  46. package/dist/execute/tasks/query.js.map +1 -0
  47. package/dist/index.js +6 -0
  48. package/dist/index.js.map +1 -0
  49. package/dist/providers/index.js +15 -0
  50. package/dist/providers/index.js.map +1 -0
  51. package/dist/providers/ollama.js +40 -0
  52. package/dist/providers/ollama.js.map +1 -0
  53. package/dist/providers/openai-compatible.js +52 -0
  54. package/dist/providers/openai-compatible.js.map +1 -0
  55. package/dist/runtime/inject.js +250 -0
  56. package/dist/runtime/inject.js.map +1 -0
  57. package/dist/schemas/agent/action.schema.js +935 -0
  58. package/dist/schemas/agent/action.schema.js.map +1 -0
  59. package/dist/schemas/agent/index.js +4 -0
  60. package/dist/schemas/agent/index.js.map +1 -0
  61. package/dist/schemas/agent/llm.schema.js +16 -0
  62. package/dist/schemas/agent/llm.schema.js.map +1 -0
  63. package/dist/schemas/agent/planner.schema.js +17 -0
  64. package/dist/schemas/agent/planner.schema.js.map +1 -0
  65. package/dist/schemas/index.js +7 -0
  66. package/dist/schemas/index.js.map +1 -0
  67. package/dist/schemas/project/context.schema.js +2 -0
  68. package/dist/schemas/project/context.schema.js.map +1 -0
  69. package/dist/schemas/project/index.js +2 -0
  70. package/dist/schemas/project/index.js.map +1 -0
  71. package/dist/schemas/runtime/index.js +4 -0
  72. package/dist/schemas/runtime/index.js.map +1 -0
  73. package/dist/schemas/runtime/injector.schema.js +11 -0
  74. package/dist/schemas/runtime/injector.schema.js.map +1 -0
  75. package/dist/schemas/runtime/runtime.schema.js +73 -0
  76. package/dist/schemas/runtime/runtime.schema.js.map +1 -0
  77. package/dist/schemas/runtime/sse.schema.js +15 -0
  78. package/dist/schemas/runtime/sse.schema.js.map +1 -0
  79. package/dist/schemas/system/index.js +2 -0
  80. package/dist/schemas/system/index.js.map +1 -0
  81. package/dist/schemas/system/logger.schema.js +56 -0
  82. package/dist/schemas/system/logger.schema.js.map +1 -0
  83. package/dist/schemas/task/index.js +9 -0
  84. package/dist/schemas/task/index.js.map +1 -0
  85. package/dist/server/app-context.js +254 -0
  86. package/dist/server/app-context.js.map +1 -0
  87. package/dist/server/config.js +22 -0
  88. package/dist/server/config.js.map +1 -0
  89. package/dist/server/error.js +22 -0
  90. package/dist/server/error.js.map +1 -0
  91. package/dist/server/event-bus.js +60 -0
  92. package/dist/server/event-bus.js.map +1 -0
  93. package/dist/server/logger.js +57 -0
  94. package/dist/server/logger.js.map +1 -0
  95. package/dist/server/run.js +265 -0
  96. package/dist/server/run.js.map +1 -0
  97. package/dist/server/sse.js +143 -0
  98. package/dist/server/sse.js.map +1 -0
  99. package/dist/ui/assets/index-C4ydQSAw.css +2 -0
  100. package/dist/ui/assets/index-Dzo7S5xs.js +85 -0
  101. package/dist/ui/favicon.svg +1 -0
  102. package/dist/ui/icons.svg +24 -0
  103. package/dist/ui/index.html +14 -0
  104. package/dist/workers/prettier.js +11 -0
  105. package/dist/workers/prettier.js.map +1 -0
  106. package/package.json +114 -0
@@ -0,0 +1,2524 @@
1
+ import fs from "fs";
2
+ import path from "path";
3
+ import { ERROR_CODES, } from "../../schemas/index.js";
4
+ /*
5
+
6
+ Never use planner methods directly in rollback handlers,
7
+ as they may have side effects that can interfere with rollback process.
8
+ Instead, implement rollback logic using direct file system operations
9
+ to ensure reliable and consistent rollbacks.
10
+
11
+ */
12
+ import mutations from "../../execute/tasks/mutations.js";
13
+ import { LoomaError } from "../../server/error.js";
14
+ /**
15
+ *
16
+ * const serializer = operationSerializers[taskName];
17
+
18
+ const operationPayload = serializer(taskResult);
19
+ *
20
+ *
21
+ */
22
+ const operationSerializers = {
23
+ ensureLibrary: ({ packageJsonPath, beforePackageJson, afterPackageJson, }) => ({
24
+ target: {
25
+ packageJsonPath,
26
+ },
27
+ before: {
28
+ packageJson: beforePackageJson,
29
+ },
30
+ after: {
31
+ packageJson: afterPackageJson,
32
+ },
33
+ }),
34
+ removeLibrary: ({ packageJsonPath, beforePackageJson, afterPackageJson, }) => ({
35
+ target: {
36
+ packageJsonPath,
37
+ },
38
+ before: {
39
+ packageJson: beforePackageJson,
40
+ },
41
+ after: {
42
+ packageJson: afterPackageJson,
43
+ },
44
+ }),
45
+ // ensureImport: ({
46
+ // payload: { code, source, importName, importType, alias },
47
+ // result: { updatedCode },
48
+ // }) => ({
49
+ // target: {
50
+ // code,
51
+ // },
52
+ // before: {
53
+ // code: code,
54
+ // },
55
+ // after: {
56
+ // code: updatedCode,
57
+ // },
58
+ // }),
59
+ removeImport: ({ payload: { code, source, importName, importType }, result: { updatedCode }, }) => ({
60
+ target: {
61
+ code: code,
62
+ source,
63
+ importName,
64
+ importType,
65
+ },
66
+ before: {
67
+ code: code,
68
+ },
69
+ after: {
70
+ code: updatedCode,
71
+ },
72
+ }),
73
+ // optimizeImports: ({ payload, result }) => ({
74
+ // target: {
75
+ // componentPath,
76
+ // },
77
+ // before: {
78
+ // code: beforeCode,
79
+ // },
80
+ // after: {
81
+ // code: afterCode,
82
+ // },
83
+ // }),
84
+ insertVariable: ({ payload: { code, variableName, value, scope, functionName }, result: { updatedCode }, }) => ({
85
+ target: {
86
+ code,
87
+ variableName,
88
+ value,
89
+ scope,
90
+ functionName,
91
+ },
92
+ before: {
93
+ code: code,
94
+ },
95
+ after: {
96
+ code: updatedCode,
97
+ },
98
+ }),
99
+ updateVariable: ({ payload: { code, variableName, newValue, line }, result: { updatedCode }, }) => ({
100
+ target: {
101
+ code,
102
+ variableName,
103
+ newValue,
104
+ },
105
+ before: {
106
+ code: code,
107
+ },
108
+ after: {
109
+ code: updatedCode,
110
+ },
111
+ }),
112
+ deleteVariable: ({ payload: { code, variableName, line }, result: { updatedCode }, }) => ({
113
+ target: {
114
+ code,
115
+ variableName,
116
+ },
117
+ before: {
118
+ code,
119
+ },
120
+ after: {
121
+ deleted: true,
122
+ },
123
+ }),
124
+ // createFunction: ({ payload, result }) => ({
125
+ // target: {
126
+ // componentPath,
127
+ // functionName,
128
+ // },
129
+ // before: {
130
+ // code: beforeCode,
131
+ // },
132
+ // after: {
133
+ // code: afterCode,
134
+ // },
135
+ // }),
136
+ // updateFunction: ({ payload, result }) => ({
137
+ // target: {
138
+ // componentPath,
139
+ // functionName,
140
+ // },
141
+ // before: {
142
+ // functionCode: beforeFunctionCode,
143
+ // },
144
+ // after: {
145
+ // functionCode: afterFunctionCode,
146
+ // },
147
+ // }),
148
+ // deleteFunction: ({ payload, result }) => ({
149
+ // target: {
150
+ // componentPath,
151
+ // functionName,
152
+ // },
153
+ // before: {
154
+ // functionCode: beforeFunctionCode,
155
+ // },
156
+ // after: {
157
+ // deleted: true,
158
+ // },
159
+ // }),
160
+ // insertCode: ({ payload, result }) => ({
161
+ // target: {
162
+ // filePath,
163
+ // },
164
+ // before: {
165
+ // code: beforeCode,
166
+ // },
167
+ // after: {
168
+ // code: beforeCode,
169
+ // },
170
+ // }),
171
+ // insertJSX: ({ payload, result }) => ({
172
+ // target: {
173
+ // componentPath,
174
+ // targetElement,
175
+ // },
176
+ // before: {
177
+ // jsx: beforeJsx,
178
+ // },
179
+ // after: {
180
+ // jsx: afterJsx,
181
+ // },
182
+ // }),
183
+ // replaceJSX: ({ payload, result }) => ({
184
+ // target: {
185
+ // componentPath,
186
+ // targetElement,
187
+ // },
188
+ // before: {
189
+ // jsx: beforeJsx,
190
+ // },
191
+ // after: {
192
+ // jsx: afterJsx,
193
+ // },
194
+ // }),
195
+ // removeJSX: ({ payload, result }) => ({
196
+ // target: {
197
+ // componentPath,
198
+ // targetElement,
199
+ // },
200
+ // before: {
201
+ // jsx: beforeJsx,
202
+ // },
203
+ // after: {
204
+ // removed: true,
205
+ // },
206
+ // }),
207
+ // wrapJSX: ({ payload, result }) => ({
208
+ // target: {
209
+ // componentPath,
210
+ // targetElement,
211
+ // },
212
+ // before: {
213
+ // jsx: beforeJsx,
214
+ // },
215
+ // after: {
216
+ // jsx: afterJsx,
217
+ // },
218
+ // }),
219
+ // moveJSX: ({ payload, result }) => ({
220
+ // target: {
221
+ // componentPath,
222
+ // sourceElement,
223
+ // destinationElement,
224
+ // },
225
+ // before: {
226
+ // sourceJSX: beforeSourceJSX,
227
+ // destinationJSX: beforeDestinationJSX,
228
+ // },
229
+ // after: {
230
+ // sourceJSX: afterSourceJSX,
231
+ // destinationJSX: afterDestinationJSX,
232
+ // },
233
+ // }),
234
+ createFile: ({ payload: { filePath, content = "" }, result }) => ({
235
+ target: {
236
+ filePath,
237
+ },
238
+ before: {
239
+ exists: false,
240
+ },
241
+ after: {
242
+ content,
243
+ },
244
+ }),
245
+ deleteFile: ({ payload: { filePath }, result: { success, filePath: flPath, trashPath }, }) => ({
246
+ target: {
247
+ originalPath: filePath,
248
+ trashPath,
249
+ },
250
+ before: {
251
+ path: filePath,
252
+ },
253
+ after: {
254
+ path: trashPath,
255
+ },
256
+ }),
257
+ renameFile: ({ payload: { oldFilePath, newFilePath }, result: { success, oldFilePath: oldPath, newFilePath: newPath }, }) => ({
258
+ target: {
259
+ oldFilePath,
260
+ newFilePath,
261
+ },
262
+ before: {
263
+ oldFilePath,
264
+ },
265
+ after: {
266
+ newFilePath,
267
+ },
268
+ }),
269
+ moveFile: ({ payload: { sourcePath, destinationPath }, result: { success, sourcePath: srcPath, destinationPath: dstPath }, }) => ({
270
+ target: {
271
+ sourcePath,
272
+ destinationPath,
273
+ },
274
+ before: {
275
+ sourcePath,
276
+ },
277
+ after: {
278
+ destinationPath,
279
+ },
280
+ }),
281
+ createDirectory: ({ payload: { directoryPath } }, context) => {
282
+ const directoryName = path.basename(directoryPath);
283
+ return {
284
+ target: {
285
+ directoryPath,
286
+ trashPath: path.join(context.project.trashDir, `${Date.now()}_${directoryName}`),
287
+ },
288
+ before: {
289
+ exists: false,
290
+ },
291
+ after: {
292
+ exists: true,
293
+ },
294
+ };
295
+ },
296
+ deleteDirectory: ({ payload: { directoryPath }, result: { trashPath } }) => ({
297
+ target: {
298
+ originalPath: directoryPath,
299
+ trashPath,
300
+ },
301
+ before: {
302
+ path: directoryPath,
303
+ },
304
+ after: {
305
+ path: trashPath,
306
+ },
307
+ }),
308
+ renameDirectory: ({ payload: { oldDirectoryPath, newDirectoryPath }, result, }) => ({
309
+ target: {
310
+ oldDirectoryPath,
311
+ newDirectoryPath,
312
+ },
313
+ before: {
314
+ oldDirectoryPath,
315
+ },
316
+ after: {
317
+ newDirectoryPath,
318
+ },
319
+ }),
320
+ moveDirectory: ({ payload: { sourcePath, destinationPath }, result }) => ({
321
+ target: {
322
+ sourcePath,
323
+ destinationPath,
324
+ },
325
+ before: {
326
+ sourcePath,
327
+ },
328
+ after: {
329
+ destinationPath,
330
+ },
331
+ }),
332
+ createComponent: ({ result: { componentDirectoryPath } }) => ({
333
+ target: {
334
+ componentDirectoryPath,
335
+ },
336
+ before: null,
337
+ after: {
338
+ componentDirectoryPath,
339
+ },
340
+ }),
341
+ updateComponent: ({ payload: { componentPath }, result: { oldComponentCode, newComponentCode }, }) => ({
342
+ target: {
343
+ componentPath,
344
+ },
345
+ before: {
346
+ componentCode: oldComponentCode,
347
+ },
348
+ after: {
349
+ componentCode: newComponentCode,
350
+ },
351
+ }),
352
+ deleteComponent: ({ payload: { componentName, parentDirectory }, result: { componentDirectoryPath, trashPath }, }) => ({
353
+ target: {
354
+ componentName,
355
+ parentDirectory,
356
+ componentDirectoryPath,
357
+ },
358
+ before: {
359
+ exists: true,
360
+ },
361
+ after: {
362
+ exists: false,
363
+ trashPath,
364
+ },
365
+ }),
366
+ moveComponent: ({ payload, result }) => ({
367
+ target: {
368
+ sourcePath: payload.sourcePath,
369
+ destinationPath: payload.destinationPath,
370
+ },
371
+ before: {
372
+ existsAt: payload.sourcePath,
373
+ },
374
+ after: {
375
+ existsAt: payload.destinationPath,
376
+ },
377
+ }),
378
+ renameComponent: ({ payload: { componentPath, updateComponentCode }, result: { renamed, oldComponentName, newComponentName, newComponentPath }, }) => ({
379
+ target: {
380
+ oldComponentpath: componentPath,
381
+ newComponentPath,
382
+ oldComponentName,
383
+ newComponentName,
384
+ },
385
+ before: {
386
+ componentName: oldComponentName,
387
+ },
388
+ after: {
389
+ componentName: newComponentName,
390
+ },
391
+ }),
392
+ // extractComponent: ({ payload: {
393
+ // parentComponentPath,
394
+ // newComponentName,
395
+ // targetJSX,
396
+ // componentsDirectory,
397
+ // includeCss}, result: {
398
+ // success,
399
+ // componentPath: newComponentPath,
400
+ // updatedParentPath: absoluteParentPath,
401
+ // } }) => ({
402
+ // target: {
403
+ // parentComponentPath,
404
+ // newComponentPath,
405
+ // },
406
+ // before: {
407
+ // parentComponentCode: beforeParentComponentCode,
408
+ // },
409
+ // after: {
410
+ // parentComponentCode: afterParentComponentCode,
411
+ // extractedComponentCode,
412
+ // },
413
+ // }),
414
+ // ensureComponentStructure: ({ payload, result }) => ({
415
+ // target: {
416
+ // componentDirectory,
417
+ // },
418
+ // before: {
419
+ // directorySnapshot: beforeDirectorySnapshot,
420
+ // },
421
+ // after: {
422
+ // directorySnapshot: afterDirectorySnapshot,
423
+ // },
424
+ // }),
425
+ // updateComponentImports: ({ payload, result }) => ({
426
+ // target: {
427
+ // componentPath,
428
+ // },
429
+ // before: {
430
+ // imports: beforeImports,
431
+ // },
432
+ // after: {
433
+ // imports: afterImports,
434
+ // },
435
+ // }),
436
+ // normalizeComponent: ({ payload, result }) => ({
437
+ // target: {
438
+ // componentPath,
439
+ // },
440
+ // before: {
441
+ // componentCode: beforeComponentCode,
442
+ // cssCode: beforeCssCode,
443
+ // },
444
+ // after: {
445
+ // componentCode: afterComponentCode,
446
+ // cssCode: afterCssCode,
447
+ // },
448
+ // }),
449
+ // ensureStyleFile: ({ payload, result }) => ({
450
+ // target: {
451
+ // cssPath,
452
+ // },
453
+ // before: {
454
+ // exists: false,
455
+ // },
456
+ // after: {
457
+ // cssCode: cssCode,
458
+ // },
459
+ // }),
460
+ insertStyles: ({ payload: { cssPath, styles, addNewLine }, result }) => ({
461
+ target: {
462
+ cssPath,
463
+ },
464
+ before: {
465
+ cssCode: styles,
466
+ },
467
+ after: {
468
+ cssCode: styles,
469
+ },
470
+ }),
471
+ updateStyles: ({ payload: { cssPath, selector, styles, createIfMissing }, result: { success, cssCode, updatedCss }, }) => ({
472
+ target: {
473
+ cssPath,
474
+ selector,
475
+ },
476
+ before: {
477
+ cssCode,
478
+ },
479
+ after: {
480
+ cssCode: updatedCss,
481
+ },
482
+ }),
483
+ removeStyles: ({ payload: { cssPath, target, removeAll }, result: { success, removed, removedCount, cssCode, updatedCss }, }) => ({
484
+ target: {
485
+ cssPath,
486
+ },
487
+ before: {
488
+ cssCode,
489
+ },
490
+ after: {
491
+ updatedCss,
492
+ },
493
+ }),
494
+ renameCssClass: ({ payload: { cssPath, componentJSXPath, oldClassName, newClassName }, result: { cssCode, updatedCssCode, jsxCode, updatedJsxCode }, }) => ({
495
+ target: {
496
+ cssPath,
497
+ componentJSXPath,
498
+ oldClassName,
499
+ newClassName,
500
+ },
501
+ before: {
502
+ cssCode: cssCode,
503
+ componentJsxCode: jsxCode,
504
+ },
505
+ after: {
506
+ cssCode: updatedCssCode,
507
+ componentJsxCode: updatedJsxCode,
508
+ },
509
+ }),
510
+ // syncComponentStyles: ({ payload, result }) => ({
511
+ // target: {
512
+ // componentPath,
513
+ // cssPath,
514
+ // },
515
+ // before: {
516
+ // componentCode: beforeComponentCode,
517
+ // cssCode: beforeCssCode,
518
+ // },
519
+ // after: {
520
+ // componentCode: afterComponentCode,
521
+ // cssCode: afterCssCode,
522
+ // },
523
+ // }),
524
+ // resolveImportConflicts: ({ payload, result }) => ({
525
+ // target: {
526
+ // componentPath,
527
+ // },
528
+ // before: {
529
+ // imports: beforeImports,
530
+ // },
531
+ // after: {
532
+ // imports: afterImports,
533
+ // },
534
+ // }),
535
+ // resolveCssClassConflicts: ({ payload, result }) => ({
536
+ // target: {
537
+ // cssPath,
538
+ // componentPath,
539
+ // },
540
+ // before: {
541
+ // componentCode: beforeComponentCode,
542
+ // cssCode: beforeCssCode,
543
+ // },
544
+ // after: {
545
+ // componentCode: afterComponentCode,
546
+ // cssCode: afterCssCode,
547
+ // },
548
+ // }),
549
+ // resolveStyleDependencies: ({ payload, result }) => ({
550
+ // target: {
551
+ // cssPath,
552
+ // },
553
+ // before: {
554
+ // imports: beforeImports,
555
+ // },
556
+ // after: {
557
+ // imports: afterImports,
558
+ // },
559
+ // }),
560
+ };
561
+ /**
562
+ * Rolls back moveComponent operation.
563
+ *
564
+ * This restores component directory
565
+ * back to its original location.
566
+ */
567
+ function undoMoveComponent(operation, appContext) {
568
+ // ----------------------------------------------------------
569
+ // STEP 1:
570
+ // Extract paths from operation
571
+ // ----------------------------------------------------------
572
+ const { sourcePath, destinationPath } = operation.target;
573
+ // ----------------------------------------------------------
574
+ // STEP 2:
575
+ // Resolve component name
576
+ // ----------------------------------------------------------
577
+ //
578
+ // Example:
579
+ //
580
+ // ../../src/components/Header
581
+ //
582
+ // -> Header
583
+ //
584
+ // ----------------------------------------------------------
585
+ const componentName = path.basename(sourcePath);
586
+ // ----------------------------------------------------------
587
+ // STEP 3:
588
+ // Build current moved path
589
+ // ----------------------------------------------------------
590
+ //
591
+ // Current location after move:
592
+ //
593
+ // destinationPath/componentName
594
+ //
595
+ // ----------------------------------------------------------
596
+ const movedComponentPath = path.join(destinationPath, componentName);
597
+ // ----------------------------------------------------------
598
+ // STEP 4:
599
+ // Ensure moved component exists
600
+ // ----------------------------------------------------------
601
+ if (!fs.existsSync(movedComponentPath)) {
602
+ throw new LoomaError(ERROR_CODES.COMPONENT_NOT_FOUND, `Moved component not found: ${movedComponentPath}`);
603
+ }
604
+ // ----------------------------------------------------------
605
+ // STEP 5:
606
+ // Ensure original parent directory exists
607
+ // ----------------------------------------------------------
608
+ //
609
+ // Example:
610
+ //
611
+ // ../../src/components/App
612
+ //
613
+ // ----------------------------------------------------------
614
+ const originalParentDirectory = path.dirname(sourcePath);
615
+ fs.mkdirSync(originalParentDirectory, {
616
+ recursive: true,
617
+ });
618
+ // ----------------------------------------------------------
619
+ // STEP 6:
620
+ // Move component back
621
+ // ----------------------------------------------------------
622
+ fs.renameSync(movedComponentPath, sourcePath);
623
+ // ----------------------------------------------------------
624
+ // STEP 7:
625
+ // Return rollback result
626
+ // ----------------------------------------------------------
627
+ return {
628
+ success: true,
629
+ restoredPath: sourcePath,
630
+ };
631
+ }
632
+ /**
633
+ * Rolls back a renameComponent operation.
634
+ *
635
+ * Params:
636
+ * - operation:
637
+ * Operation log entry created by appendOperation.
638
+ *
639
+ * Returns:
640
+ * - {
641
+ * rolledBack: boolean,
642
+ * componentPath: string
643
+ * }
644
+ */
645
+ function undoRenameComponent(operation, appContext) {
646
+ // ----------------------------------------------------------
647
+ // STEP 1:
648
+ // Extract information from operation log.
649
+ // ----------------------------------------------------------
650
+ const { newComponentPath: componentPath } = operation.target;
651
+ const { componentName: oldComponentName } = operation.before;
652
+ const { componentName: newComponentName } = operation.after;
653
+ // ----------------------------------------------------------
654
+ // STEP 2:
655
+ // Rename component back to its original name.
656
+ // ----------------------------------------------------------
657
+ const result = mutations.renameComponent({
658
+ componentPath,
659
+ newComponentName: oldComponentName,
660
+ // Preserve the same behavior that was
661
+ // used during the original rename.
662
+ updateComponentCode: true,
663
+ }, appContext);
664
+ // ----------------------------------------------------------
665
+ // STEP 3:
666
+ // Validate rollback.
667
+ // ----------------------------------------------------------
668
+ if (!result?.success) {
669
+ throw new LoomaError(ERROR_CODES.ROLLBACK_ERROR, `Failed to rollback renameComponent: ${newComponentName} -> ${oldComponentName}`);
670
+ }
671
+ // ----------------------------------------------------------
672
+ // STEP 4:
673
+ // Return result.
674
+ // ----------------------------------------------------------
675
+ return {
676
+ success: true,
677
+ componentPath,
678
+ };
679
+ }
680
+ function undoCreateComponent(operation, appContext) {
681
+ fs.rmSync(path.resolve(appContext.project.root, operation.target.componentDirectoryPath), {
682
+ recursive: true,
683
+ force: true,
684
+ });
685
+ return {
686
+ success: true,
687
+ };
688
+ }
689
+ function undoDeleteComponent(operation, appContext) {
690
+ // ----------------------------------------------------------
691
+ // Resolve source directory inside trash.
692
+ // ----------------------------------------------------------
693
+ const sourcePath = path.resolve(appContext.project.root, operation.after.trashPath);
694
+ // ----------------------------------------------------------
695
+ // Resolve original component path.
696
+ // Example:
697
+ // src/components/Home
698
+ // ----------------------------------------------------------
699
+ const destinationPath = path.resolve(appContext.project.root, operation.target.componentDirectoryPath);
700
+ // ----------------------------------------------------------
701
+ // Make sure parent directory exists.
702
+ // ----------------------------------------------------------
703
+ const parentDirectory = path.dirname(destinationPath);
704
+ fs.mkdirSync(parentDirectory, {
705
+ recursive: true,
706
+ });
707
+ // ----------------------------------------------------------
708
+ // Restore directory with its original name.
709
+ // ----------------------------------------------------------
710
+ fs.renameSync(sourcePath, destinationPath);
711
+ return {
712
+ success: true,
713
+ sourcePath,
714
+ destinationPath,
715
+ };
716
+ }
717
+ /**
718
+ * Rolls back insertCode operation.
719
+ *
720
+ * Restores file content back
721
+ * to original state before insertion.
722
+ */
723
+ // function undoInsertCode(
724
+ // operation
725
+ // ): TaskResponse<any> {
726
+ // // ----------------------------------------------------------
727
+ // // STEP 1:
728
+ // // Extract file path
729
+ // // ----------------------------------------------------------
730
+ // const { filePath } = operation.target;
731
+ // // ----------------------------------------------------------
732
+ // // STEP 2:
733
+ // // Extract original file content
734
+ // // ----------------------------------------------------------
735
+ // const originalCode = operation.before.code;
736
+ // // ----------------------------------------------------------
737
+ // // STEP 3:
738
+ // // Ensure rollback data exists
739
+ // // ----------------------------------------------------------
740
+ // if (typeof originalCode !== "string") {
741
+ // throw new LoomaError(ERROR_CODES.COMPONENT_NOT_FOUND,"Missing original code for rollback.");
742
+ // }
743
+ // // ----------------------------------------------------------
744
+ // // STEP 4:
745
+ // // Restore original file content
746
+ // // ----------------------------------------------------------
747
+ // fs.writeFileSync(filePath, originalCode, "utf8");
748
+ // // ----------------------------------------------------------
749
+ // // STEP 5:
750
+ // // Return rollback result
751
+ // // ----------------------------------------------------------
752
+ // return {
753
+ // success: true,
754
+ // restoredFilePath: filePath,
755
+ // };
756
+ // }
757
+ /**
758
+ * Rolls back extractComponent operation.
759
+ *
760
+ * This:
761
+ * - restores original parent component code
762
+ * - removes extracted component directory
763
+ */
764
+ function undoExtractComponent(operation, appContext) {
765
+ // ----------------------------------------------------------
766
+ // STEP 1:
767
+ // Extract rollback information
768
+ // ----------------------------------------------------------
769
+ const { parentComponentPath, newComponentPath } = operation.target;
770
+ // ----------------------------------------------------------
771
+ // STEP 2:
772
+ // Extract original parent component code
773
+ // ----------------------------------------------------------
774
+ const originalParentCode = operation.before.parentComponentCode;
775
+ // ----------------------------------------------------------
776
+ // STEP 3:
777
+ // Ensure rollback snapshot exists
778
+ // ----------------------------------------------------------
779
+ if (typeof originalParentCode !== "string") {
780
+ throw new LoomaError(ERROR_CODES.COMPONENT_NOT_FOUND, "Missing parent component snapshot.");
781
+ }
782
+ // ----------------------------------------------------------
783
+ // STEP 4:
784
+ // Restore original parent component
785
+ // ----------------------------------------------------------
786
+ fs.writeFileSync(parentComponentPath, originalParentCode, "utf8");
787
+ // ----------------------------------------------------------
788
+ // STEP 5:
789
+ // Remove extracted component directory
790
+ // ----------------------------------------------------------
791
+ //
792
+ // Example:
793
+ //
794
+ // /src/components/Header
795
+ //
796
+ // ----------------------------------------------------------
797
+ if (fs.existsSync(newComponentPath)) {
798
+ fs.rmSync(newComponentPath, {
799
+ recursive: true,
800
+ force: true,
801
+ });
802
+ }
803
+ // ----------------------------------------------------------
804
+ // STEP 6:
805
+ // Return rollback result
806
+ // ----------------------------------------------------------
807
+ return {
808
+ success: true,
809
+ restoredParent: parentComponentPath,
810
+ removedComponent: newComponentPath,
811
+ };
812
+ }
813
+ /**
814
+ * Rolls back insertJSX operation.
815
+ *
816
+ * Restores component source code
817
+ * back to original state before JSX insertion.
818
+ */
819
+ // function undoInsertJSX(
820
+ // operation
821
+ // ): TaskResponse<any> {
822
+ // // ----------------------------------------------------------
823
+ // // STEP 1:
824
+ // // Extract component file path
825
+ // // ----------------------------------------------------------
826
+ // const { componentPath } = operation.target;
827
+ // // ----------------------------------------------------------
828
+ // // STEP 2:
829
+ // // Extract original component code
830
+ // // ----------------------------------------------------------
831
+ // const originalCode = operation.before.code;
832
+ // // ----------------------------------------------------------
833
+ // // STEP 3:
834
+ // // Ensure rollback snapshot exists
835
+ // // ----------------------------------------------------------
836
+ // if (typeof originalCode !== "string") {
837
+ // throw new LoomaError(ERROR_CODES.COMPONENT_NOT_FOUND,"Missing original component code for rollback.");
838
+ // }
839
+ // // ----------------------------------------------------------
840
+ // // STEP 4:
841
+ // // Restore original component code
842
+ // // ----------------------------------------------------------
843
+ // fs.writeFileSync(componentPath, originalCode, "utf8");
844
+ // // ----------------------------------------------------------
845
+ // // STEP 5:
846
+ // // Return rollback result
847
+ // // ----------------------------------------------------------
848
+ // return {
849
+ // success: true,
850
+ // restoredComponent: componentPath,
851
+ // };
852
+ // }
853
+ /**
854
+ * Rolls back replaceJSX operation.
855
+ *
856
+ * Restores component source code
857
+ * back to original state before JSX replacement.
858
+ */
859
+ // function undoReplaceJSX(
860
+ // operation
861
+ // ): TaskResponse<any> {
862
+ // // ----------------------------------------------------------
863
+ // // STEP 1:
864
+ // // Extract component file path
865
+ // // ----------------------------------------------------------
866
+ // const { componentPath } = operation.target;
867
+ // // ----------------------------------------------------------
868
+ // // STEP 2:
869
+ // // Extract original component code
870
+ // // ----------------------------------------------------------
871
+ // const originalCode = operation.before.code;
872
+ // // ----------------------------------------------------------
873
+ // // STEP 3:
874
+ // // Ensure rollback snapshot exists
875
+ // // ----------------------------------------------------------
876
+ // if (typeof originalCode !== "string") {
877
+ // throw new LoomaError(ERROR_CODES.COMPONENT_NOT_FOUND,"Missing original component code for rollback.");
878
+ // }
879
+ // // ----------------------------------------------------------
880
+ // // STEP 4:
881
+ // // Restore original component code
882
+ // // ----------------------------------------------------------
883
+ // fs.writeFileSync(componentPath, originalCode, "utf8");
884
+ // // ----------------------------------------------------------
885
+ // // STEP 5:
886
+ // // Return rollback result
887
+ // // ----------------------------------------------------------
888
+ // return {
889
+ // success: true,
890
+ // restoredComponent: componentPath,
891
+ // };
892
+ // }
893
+ /**
894
+ * Rolls back removeJSX operation.
895
+ *
896
+ * Restores component source code
897
+ * back to original state before JSX removal.
898
+ */
899
+ // function undoRemoveJSX(
900
+ // operation
901
+ // ): TaskResponse<any> {
902
+ // // ----------------------------------------------------------
903
+ // // STEP 1:
904
+ // // Extract component file path
905
+ // // ----------------------------------------------------------
906
+ // const { componentPath } = operation.target;
907
+ // // ----------------------------------------------------------
908
+ // // STEP 2:
909
+ // // Extract original component code
910
+ // // ----------------------------------------------------------
911
+ // const originalCode = operation.before.code;
912
+ // // ----------------------------------------------------------
913
+ // // STEP 3:
914
+ // // Ensure rollback snapshot exists
915
+ // // ----------------------------------------------------------
916
+ // if (typeof originalCode !== "string") {
917
+ // throw new LoomaError(ERROR_CODES.COMPONENT_NOT_FOUND,"Missing original component code for rollback.");
918
+ // }
919
+ // // ----------------------------------------------------------
920
+ // // STEP 4:
921
+ // // Restore original component code
922
+ // // ----------------------------------------------------------
923
+ // fs.writeFileSync(componentPath, originalCode, "utf8");
924
+ // // ----------------------------------------------------------
925
+ // // STEP 5:
926
+ // // Return rollback result
927
+ // // ----------------------------------------------------------
928
+ // return {
929
+ // success: true,
930
+ // restoredComponent: componentPath,
931
+ // };
932
+ // }
933
+ /**
934
+ * Rolls back moveJSX operation.
935
+ *
936
+ * Restores component source code
937
+ * back to original state before JSX movement.
938
+ */
939
+ // function undoMoveJSX(
940
+ // operation
941
+ // ): TaskResponse<any> {
942
+ // // ----------------------------------------------------------
943
+ // // STEP 1:
944
+ // // Extract component file path
945
+ // // ----------------------------------------------------------
946
+ // const { componentPath } = operation.target;
947
+ // // ----------------------------------------------------------
948
+ // // STEP 2:
949
+ // // Extract original component code
950
+ // // ----------------------------------------------------------
951
+ // const originalCode = operation.before.code;
952
+ // // ----------------------------------------------------------
953
+ // // STEP 3:
954
+ // // Ensure rollback snapshot exists
955
+ // // ----------------------------------------------------------
956
+ // if (typeof originalCode !== "string") {
957
+ // throw new LoomaError(ERROR_CODES.COMPONENT_NOT_FOUND,"Missing original component code for rollback.");
958
+ // }
959
+ // // ----------------------------------------------------------
960
+ // // STEP 4:
961
+ // // Restore original component code
962
+ // // ----------------------------------------------------------
963
+ // fs.writeFileSync(componentPath, originalCode, "utf8");
964
+ // // ----------------------------------------------------------
965
+ // // STEP 5:
966
+ // // Return rollback result
967
+ // // ----------------------------------------------------------
968
+ // return {
969
+ // success: true,
970
+ // restoredComponent: componentPath,
971
+ // };
972
+ // }
973
+ /**
974
+ * Rolls back wrapJSX operation.
975
+ *
976
+ * Restores component source code
977
+ * back to original state before JSX wrapping.
978
+ */
979
+ // function undoWrapJSX(
980
+ // operation
981
+ // ): TaskResponse<any> {
982
+ // // ----------------------------------------------------------
983
+ // // STEP 1:
984
+ // // Extract component file path
985
+ // // ----------------------------------------------------------
986
+ // const { componentPath } = operation.target;
987
+ // // ----------------------------------------------------------
988
+ // // STEP 2:
989
+ // // Extract original component code
990
+ // // ----------------------------------------------------------
991
+ // const originalCode = operation.before.code;
992
+ // // ----------------------------------------------------------
993
+ // // STEP 3:
994
+ // // Ensure rollback snapshot exists
995
+ // // ----------------------------------------------------------
996
+ // if (typeof originalCode !== "string") {
997
+ // throw new LoomaError(ERROR_CODES.COMPONENT_NOT_FOUND,"Missing original component code for rollback.");
998
+ // }
999
+ // // ----------------------------------------------------------
1000
+ // // STEP 4:
1001
+ // // Restore original component code
1002
+ // // ----------------------------------------------------------
1003
+ // fs.writeFileSync(componentPath, originalCode, "utf8");
1004
+ // // ----------------------------------------------------------
1005
+ // // STEP 5:
1006
+ // // Return rollback result
1007
+ // // ----------------------------------------------------------
1008
+ // return {
1009
+ // success: true,
1010
+ // restoredComponent: componentPath,
1011
+ // };
1012
+ // }
1013
+ /**
1014
+ * Rolls back createFile operation.
1015
+ *
1016
+ * Removes file that was created
1017
+ * during createFile task execution.
1018
+ */
1019
+ function undoCreateFile(operation, appContext) {
1020
+ // ----------------------------------------------------------
1021
+ // STEP 1:
1022
+ // Extract file path
1023
+ // ----------------------------------------------------------
1024
+ const { filePath } = operation.target;
1025
+ // ----------------------------------------------------------
1026
+ // STEP 2:
1027
+ // Ensure file exists
1028
+ // ----------------------------------------------------------
1029
+ if (!fs.existsSync(filePath)) {
1030
+ throw new LoomaError(ERROR_CODES.FILE_NOT_FOUND, `File does not exist: ${filePath}`);
1031
+ }
1032
+ // ----------------------------------------------------------
1033
+ // STEP 3:
1034
+ // Remove created file
1035
+ // ----------------------------------------------------------
1036
+ fs.unlinkSync(filePath);
1037
+ // ----------------------------------------------------------
1038
+ // STEP 4:
1039
+ // Return rollback result
1040
+ // ----------------------------------------------------------
1041
+ return {
1042
+ success: true,
1043
+ removedFile: filePath,
1044
+ };
1045
+ }
1046
+ /**
1047
+ * Rolls back deleteFile operation.
1048
+ *
1049
+ * Restores deleted file
1050
+ * back to original location.
1051
+ */
1052
+ function undoDeleteFile(operation, appContext) {
1053
+ // ----------------------------------------------------------
1054
+ // STEP 1:
1055
+ // Extract file paths
1056
+ // ----------------------------------------------------------
1057
+ const { originalPath, trashPath } = operation.target;
1058
+ // ----------------------------------------------------------
1059
+ // STEP 2:
1060
+ // Ensure deleted file exists in trash
1061
+ // ----------------------------------------------------------
1062
+ if (!fs.existsSync(trashPath)) {
1063
+ throw new LoomaError(ERROR_CODES.FILE_NOT_FOUND, `Deleted file not found in trash: ${trashPath}`);
1064
+ }
1065
+ // ----------------------------------------------------------
1066
+ // STEP 3:
1067
+ // Ensure original parent directory exists
1068
+ // ----------------------------------------------------------
1069
+ const parentDirectory = path.dirname(originalPath);
1070
+ fs.mkdirSync(parentDirectory, {
1071
+ recursive: true,
1072
+ });
1073
+ // ----------------------------------------------------------
1074
+ // STEP 4:
1075
+ // Restore file back
1076
+ // ----------------------------------------------------------
1077
+ fs.renameSync(trashPath, originalPath);
1078
+ // ----------------------------------------------------------
1079
+ // STEP 5:
1080
+ // Return rollback result
1081
+ // ----------------------------------------------------------
1082
+ return {
1083
+ success: true,
1084
+ restoredFile: originalPath,
1085
+ };
1086
+ }
1087
+ /**
1088
+ * Rolls back renameFile operation.
1089
+ *
1090
+ * Renames file back
1091
+ * to its original path.
1092
+ */
1093
+ function undoRenameFile(operation, appContext) {
1094
+ // ----------------------------------------------------------
1095
+ // STEP 1:
1096
+ // Extract file paths
1097
+ // ----------------------------------------------------------
1098
+ const { oldFilePath, newFilePath } = operation.target;
1099
+ // ----------------------------------------------------------
1100
+ // STEP 2:
1101
+ // Ensure renamed file exists
1102
+ // ----------------------------------------------------------
1103
+ if (!fs.existsSync(newFilePath)) {
1104
+ throw new LoomaError(ERROR_CODES.FILE_NOT_FOUND, `Renamed file not found: ${newFilePath}`);
1105
+ }
1106
+ // ----------------------------------------------------------
1107
+ // STEP 3:
1108
+ // Ensure original parent directory exists
1109
+ // ----------------------------------------------------------
1110
+ const parentDirectory = path.dirname(oldFilePath);
1111
+ fs.mkdirSync(parentDirectory, {
1112
+ recursive: true,
1113
+ });
1114
+ // ----------------------------------------------------------
1115
+ // STEP 4:
1116
+ // Rename file back
1117
+ // ----------------------------------------------------------
1118
+ fs.renameSync(newFilePath, oldFilePath);
1119
+ // ----------------------------------------------------------
1120
+ // STEP 5:
1121
+ // Return rollback result
1122
+ // ----------------------------------------------------------
1123
+ return {
1124
+ success: true,
1125
+ restoredFile: oldFilePath,
1126
+ };
1127
+ }
1128
+ /**
1129
+ * Rolls back moveFile operation.
1130
+ *
1131
+ * Moves file back
1132
+ * to its original location.
1133
+ */
1134
+ function undoMoveFile(operation, appContext) {
1135
+ // ----------------------------------------------------------
1136
+ // STEP 1:
1137
+ // Extract file paths
1138
+ // ----------------------------------------------------------
1139
+ const { sourcePath, destinationPath } = operation.target;
1140
+ // ----------------------------------------------------------
1141
+ // STEP 2:
1142
+ // Resolve moved file path
1143
+ // ----------------------------------------------------------
1144
+ //
1145
+ // Example:
1146
+ //
1147
+ // sourcePath:
1148
+ // /src/tasks/helpers/api.js
1149
+ //
1150
+ // destinationPath:
1151
+ // /src/services
1152
+ //
1153
+ // moved file:
1154
+ // /src/services/api.js
1155
+ //
1156
+ // ----------------------------------------------------------
1157
+ const fileName = path.basename(sourcePath);
1158
+ // const dstFileName = path.basename(destinationPath);
1159
+ const movedFilePath = path.join(destinationPath, fileName);
1160
+ // ----------------------------------------------------------
1161
+ // STEP 3:
1162
+ // Ensure moved file exists
1163
+ // ----------------------------------------------------------
1164
+ if (!fs.existsSync(movedFilePath)) {
1165
+ throw new LoomaError(ERROR_CODES.FILE_NOT_FOUND, `Moved file not found: ${movedFilePath}`);
1166
+ }
1167
+ // ----------------------------------------------------------
1168
+ // STEP 4:
1169
+ // Ensure original parent directory exists
1170
+ // ----------------------------------------------------------
1171
+ const originalParentDirectory = path.dirname(sourcePath);
1172
+ fs.mkdirSync(originalParentDirectory, {
1173
+ recursive: true,
1174
+ });
1175
+ // ----------------------------------------------------------
1176
+ // STEP 5:
1177
+ // Move file back
1178
+ // ----------------------------------------------------------
1179
+ fs.renameSync(movedFilePath, sourcePath);
1180
+ // ----------------------------------------------------------
1181
+ // STEP 6:
1182
+ // Return rollback result
1183
+ // ----------------------------------------------------------
1184
+ return {
1185
+ success: true,
1186
+ restoredFile: sourcePath,
1187
+ };
1188
+ }
1189
+ /**
1190
+ * Rolls back createDirectory operation.
1191
+ *
1192
+ * Removes directory that was created
1193
+ * during createDirectory task execution.
1194
+ */
1195
+ function undoCreateDirectory(operation, appContext) {
1196
+ // ----------------------------------------------------------
1197
+ // STEP 1:
1198
+ // Extract paths
1199
+ // ----------------------------------------------------------
1200
+ const { directoryPath, trashPath } = operation.target;
1201
+ // ----------------------------------------------------------
1202
+ // STEP 2:
1203
+ // Ensure directory exists
1204
+ // ----------------------------------------------------------
1205
+ if (!fs.existsSync(directoryPath)) {
1206
+ throw new LoomaError(ERROR_CODES.DIRECTORY_NOT_FOUND, `Directory not found: ${directoryPath}`);
1207
+ }
1208
+ // ----------------------------------------------------------
1209
+ // STEP 3:
1210
+ // Ensure trash parent exists
1211
+ // ----------------------------------------------------------
1212
+ fs.mkdirSync(path.dirname(trashPath), {
1213
+ recursive: true,
1214
+ });
1215
+ // ----------------------------------------------------------
1216
+ // STEP 4:
1217
+ // Move directory to trash
1218
+ // ----------------------------------------------------------
1219
+ fs.renameSync(directoryPath, trashPath);
1220
+ // ----------------------------------------------------------
1221
+ // STEP 5:
1222
+ // Return result
1223
+ // ----------------------------------------------------------
1224
+ return {
1225
+ success: true,
1226
+ removedDirectory: directoryPath,
1227
+ };
1228
+ }
1229
+ /**
1230
+ * Rolls back deleteDirectory operation.
1231
+ *
1232
+ * Restores deleted directory
1233
+ * back to original location.
1234
+ */
1235
+ function undoDeleteDirectory(operation, appContext) {
1236
+ // ----------------------------------------------------------
1237
+ // STEP 1:
1238
+ // Extract directory paths
1239
+ // ----------------------------------------------------------
1240
+ const { originalPath, trashPath } = operation.target;
1241
+ // ----------------------------------------------------------
1242
+ // STEP 2:
1243
+ // Ensure deleted directory exists in trash
1244
+ // ----------------------------------------------------------
1245
+ if (!fs.existsSync(trashPath)) {
1246
+ throw new LoomaError(ERROR_CODES.DIRECTORY_NOT_FOUND, `Deleted directory not found in trash: ${trashPath}`);
1247
+ }
1248
+ // ----------------------------------------------------------
1249
+ // STEP 3:
1250
+ // Ensure original parent directory exists
1251
+ // ----------------------------------------------------------
1252
+ const parentDirectory = path.dirname(originalPath);
1253
+ fs.mkdirSync(parentDirectory, {
1254
+ recursive: true,
1255
+ });
1256
+ // ----------------------------------------------------------
1257
+ // STEP 4:
1258
+ // Restore directory back
1259
+ // ----------------------------------------------------------
1260
+ fs.renameSync(trashPath, originalPath);
1261
+ // ----------------------------------------------------------
1262
+ // STEP 5:
1263
+ // Return rollback result
1264
+ // ----------------------------------------------------------
1265
+ return {
1266
+ success: true,
1267
+ restoredDirectory: originalPath,
1268
+ };
1269
+ }
1270
+ /**
1271
+ * Rolls back renameDirectory operation.
1272
+ *
1273
+ * Renames directory back
1274
+ * to its original path.
1275
+ */
1276
+ function undoRenameDirectory(operation, appContext) {
1277
+ // ----------------------------------------------------------
1278
+ // STEP 1:
1279
+ // Extract directory paths
1280
+ // ----------------------------------------------------------
1281
+ const { oldDirectoryPath, newDirectoryPath } = operation.target;
1282
+ // ----------------------------------------------------------
1283
+ // STEP 2:
1284
+ // Ensure renamed directory exists
1285
+ // ----------------------------------------------------------
1286
+ if (!fs.existsSync(newDirectoryPath)) {
1287
+ throw new LoomaError(ERROR_CODES.DIRECTORY_NOT_FOUND, `Renamed directory not found: ${newDirectoryPath}`);
1288
+ }
1289
+ // ----------------------------------------------------------
1290
+ // STEP 3:
1291
+ // Ensure original parent directory exists
1292
+ // ----------------------------------------------------------
1293
+ const parentDirectory = path.dirname(oldDirectoryPath);
1294
+ fs.mkdirSync(parentDirectory, {
1295
+ recursive: true,
1296
+ });
1297
+ // ----------------------------------------------------------
1298
+ // STEP 4:
1299
+ // Rename directory back
1300
+ // ----------------------------------------------------------
1301
+ fs.renameSync(newDirectoryPath, oldDirectoryPath);
1302
+ // ----------------------------------------------------------
1303
+ // STEP 5:
1304
+ // Return rollback result
1305
+ // ----------------------------------------------------------
1306
+ return {
1307
+ success: true,
1308
+ restoredDirectory: oldDirectoryPath,
1309
+ };
1310
+ }
1311
+ /**
1312
+ * Rolls back moveDirectory operation.
1313
+ *
1314
+ * Moves directory back
1315
+ * to its original location.
1316
+ */
1317
+ function undoMoveDirectory(operation, appContext) {
1318
+ // ----------------------------------------------------------
1319
+ // STEP 1:
1320
+ // Extract paths
1321
+ // ----------------------------------------------------------
1322
+ const { sourcePath, destinationPath } = operation.target;
1323
+ // ----------------------------------------------------------
1324
+ // STEP 2:
1325
+ // Determine moved directory path
1326
+ // ----------------------------------------------------------
1327
+ const directoryName = path.basename(sourcePath);
1328
+ const movedDirectoryPath = path.join(destinationPath, directoryName);
1329
+ // ----------------------------------------------------------
1330
+ // STEP 3:
1331
+ // Ensure moved directory exists
1332
+ // ----------------------------------------------------------
1333
+ if (!fs.existsSync(movedDirectoryPath)) {
1334
+ throw new LoomaError(ERROR_CODES.DIRECTORY_NOT_FOUND, `Moved directory not found: ${movedDirectoryPath}`);
1335
+ }
1336
+ // ----------------------------------------------------------
1337
+ // STEP 4:
1338
+ // Ensure original parent directory exists
1339
+ // ----------------------------------------------------------
1340
+ const originalParentDirectory = path.dirname(sourcePath);
1341
+ fs.mkdirSync(originalParentDirectory, {
1342
+ recursive: true,
1343
+ });
1344
+ // ----------------------------------------------------------
1345
+ // STEP 5:
1346
+ // Move directory back
1347
+ // ----------------------------------------------------------
1348
+ fs.renameSync(movedDirectoryPath, sourcePath);
1349
+ // ----------------------------------------------------------
1350
+ // STEP 6:
1351
+ // Return rollback result
1352
+ // ----------------------------------------------------------
1353
+ return {
1354
+ success: true,
1355
+ restoredDirectory: sourcePath,
1356
+ };
1357
+ }
1358
+ /**
1359
+ * Rolls back insertStyles operation.
1360
+ *
1361
+ * Restores CSS file content
1362
+ * back to original state before style insertion.
1363
+ */
1364
+ // function undoInsertStyles(
1365
+ // operation
1366
+ // ): TaskResponse<any> {
1367
+ // // ----------------------------------------------------------
1368
+ // // STEP 1:
1369
+ // // Extract CSS file path
1370
+ // // ----------------------------------------------------------
1371
+ // const { cssPath } = operation.target;
1372
+ // // ----------------------------------------------------------
1373
+ // // STEP 2:
1374
+ // // Extract original CSS content
1375
+ // // ----------------------------------------------------------
1376
+ // const originalCss = operation.before.cssCode;
1377
+ // // ----------------------------------------------------------
1378
+ // // STEP 3:
1379
+ // // Ensure rollback snapshot exists
1380
+ // // ----------------------------------------------------------
1381
+ // if (typeof originalCss !== "string") {
1382
+ // throw new LoomaError(ERROR_CODES.COMPONENT_NOT_FOUND,"Missing original CSS code for rollback.");
1383
+ // }
1384
+ // // ----------------------------------------------------------
1385
+ // // STEP 4:
1386
+ // // Restore original CSS content
1387
+ // // ----------------------------------------------------------
1388
+ // fs.writeFileSync(cssPath, originalCss, "utf8");
1389
+ // // ----------------------------------------------------------
1390
+ // // STEP 5:
1391
+ // // Return rollback result
1392
+ // // ----------------------------------------------------------
1393
+ // return {
1394
+ // success: true,
1395
+ // restoredCssFile: cssPath,
1396
+ // };
1397
+ // }
1398
+ /**
1399
+ * Rolls back updateStyles operation.
1400
+ *
1401
+ * Restores CSS file content
1402
+ * back to original state before style update.
1403
+ */
1404
+ function undoUpdateStyles(operation, appContext) {
1405
+ // ----------------------------------------------------------
1406
+ // STEP 1:
1407
+ // Extract CSS file path
1408
+ // ----------------------------------------------------------
1409
+ const { cssPath } = operation.target;
1410
+ // ----------------------------------------------------------
1411
+ // STEP 2:
1412
+ // Extract original CSS content
1413
+ // ----------------------------------------------------------
1414
+ const originalCss = operation.before.cssCode;
1415
+ // ----------------------------------------------------------
1416
+ // STEP 3:
1417
+ // Ensure rollback snapshot exists
1418
+ // ----------------------------------------------------------
1419
+ if (typeof originalCss !== "string") {
1420
+ throw new LoomaError(ERROR_CODES.CSS_NOT_FOUND, "Missing original CSS code for rollback.");
1421
+ }
1422
+ // ----------------------------------------------------------
1423
+ // STEP 4:
1424
+ // Restore original CSS content
1425
+ // ----------------------------------------------------------
1426
+ fs.writeFileSync(cssPath, originalCss, "utf8");
1427
+ // ----------------------------------------------------------
1428
+ // STEP 5:
1429
+ // Return rollback result
1430
+ // ----------------------------------------------------------
1431
+ return {
1432
+ success: true,
1433
+ restoredCssFile: cssPath,
1434
+ };
1435
+ }
1436
+ /**
1437
+ * Rolls back removeStyles operation.
1438
+ *
1439
+ * Restores CSS file content
1440
+ * back to original state before style removal.
1441
+ */
1442
+ function undoRemoveStyles(operation, appContext) {
1443
+ // ----------------------------------------------------------
1444
+ // STEP 1:
1445
+ // Extract CSS file path
1446
+ // ----------------------------------------------------------
1447
+ const { cssPath } = operation.target;
1448
+ // ----------------------------------------------------------
1449
+ // STEP 2:
1450
+ // Extract original CSS content
1451
+ // ----------------------------------------------------------
1452
+ const originalCss = operation.before.cssCode;
1453
+ // ----------------------------------------------------------
1454
+ // STEP 3:
1455
+ // Ensure rollback snapshot exists
1456
+ // ----------------------------------------------------------
1457
+ if (typeof originalCss !== "string") {
1458
+ throw new LoomaError(ERROR_CODES.CSS_NOT_FOUND, "Missing original CSS code for rollback.");
1459
+ }
1460
+ // ----------------------------------------------------------
1461
+ // STEP 4:
1462
+ // Restore original CSS content
1463
+ // ----------------------------------------------------------
1464
+ fs.writeFileSync(cssPath, originalCss, "utf8");
1465
+ // ----------------------------------------------------------
1466
+ // STEP 5:
1467
+ // Return rollback result
1468
+ // ----------------------------------------------------------
1469
+ return {
1470
+ success: true,
1471
+ restoredCssFile: cssPath,
1472
+ };
1473
+ }
1474
+ /**
1475
+ * Restores CSS and JSX files
1476
+ * to state before renameCssClass.
1477
+ */
1478
+ function undoRenameCssClass(operation, appContext) {
1479
+ // ----------------------------------------------------------
1480
+ // STEP 1:
1481
+ // Extract target files
1482
+ // ----------------------------------------------------------
1483
+ const { cssPath, componentJSXPath } = operation.target;
1484
+ // ----------------------------------------------------------
1485
+ // STEP 2:
1486
+ // Extract original contents
1487
+ // ----------------------------------------------------------
1488
+ const { cssCode, jsxCode } = operation.before;
1489
+ // ----------------------------------------------------------
1490
+ // STEP 3:
1491
+ // Validate snapshots
1492
+ // ----------------------------------------------------------
1493
+ if (typeof cssCode !== "string") {
1494
+ throw new LoomaError(ERROR_CODES.CSS_NOT_FOUND, "Missing cssCode in operation.before");
1495
+ }
1496
+ if (typeof jsxCode !== "string") {
1497
+ throw new LoomaError(ERROR_CODES.JSX_NOT_FOUND, "Missing jsxCode in operation.before");
1498
+ }
1499
+ // ----------------------------------------------------------
1500
+ // STEP 4:
1501
+ // Restore CSS file
1502
+ // ----------------------------------------------------------
1503
+ fs.writeFileSync(cssPath, cssCode, "utf8");
1504
+ // ----------------------------------------------------------
1505
+ // STEP 5:
1506
+ // Restore JSX file
1507
+ // ----------------------------------------------------------
1508
+ fs.writeFileSync(componentJSXPath, jsxCode, "utf8");
1509
+ // ----------------------------------------------------------
1510
+ // STEP 6:
1511
+ // Return result
1512
+ // ----------------------------------------------------------
1513
+ return {
1514
+ success: true,
1515
+ cssPath,
1516
+ componentJSXPath,
1517
+ };
1518
+ }
1519
+ // function undoRemoveImport(
1520
+ // operation
1521
+ // ): TaskResponse<any> {
1522
+ // return {
1523
+ // success: true,
1524
+ // updatedCode: operation.before.code,
1525
+ // };
1526
+ // }
1527
+ // function undoInsertVariable(
1528
+ // operation
1529
+ // ): TaskResponse<any> {
1530
+ // return {
1531
+ // success: true,
1532
+ // updatedCode: operation.before.code,
1533
+ // };
1534
+ // }
1535
+ // function undoUpdateVariable(
1536
+ // operation
1537
+ // ): TaskResponse<any> {
1538
+ // return {
1539
+ // success: true,
1540
+ // updatedCode: operation.before.code,
1541
+ // };
1542
+ // }
1543
+ // function undoDeleteVariable(
1544
+ // operation
1545
+ // ): TaskResponse<any> {
1546
+ // return {
1547
+ // success: true,
1548
+ // updatedCode: operation.before.code,
1549
+ // };
1550
+ // }
1551
+ /**
1552
+ * Restores a directory from .looma-trash to its original location.
1553
+ *
1554
+ * Params:
1555
+ * - trashPath:
1556
+ * Relative path of the directory inside .looma-trash.
1557
+ *
1558
+ * - originalPath:
1559
+ * Original relative path of the directory before deletion.
1560
+ *
1561
+ * Returns:
1562
+ * {
1563
+ * success: boolean,
1564
+ * trashPath: string,
1565
+ * originalPath: string
1566
+ * }
1567
+ */
1568
+ // function restoreDirectory({ trashPath, originalPath }) {
1569
+ // // ----------------------------------------------------------
1570
+ // // STEP 1:
1571
+ // // Convert relative paths to absolute paths.
1572
+ // // ----------------------------------------------------------
1573
+ // const absoluteTrashPath = path.resolve(process.cwd(), trashPath);
1574
+ // const absoluteOriginalPath = path.resolve(process.cwd(), originalPath);
1575
+ // // ----------------------------------------------------------
1576
+ // // STEP 2:
1577
+ // // Verify that the directory exists in trash.
1578
+ // // ----------------------------------------------------------
1579
+ // if (!fs.existsSync(absoluteTrashPath)) {
1580
+ // return {
1581
+ // success: false,
1582
+ // message: "Directory does not exist in trash",
1583
+ // trashPath,
1584
+ // originalPath,
1585
+ // };
1586
+ // }
1587
+ // // ----------------------------------------------------------
1588
+ // // STEP 3:
1589
+ // // Ensure parent directory exists.
1590
+ // //
1591
+ // // Example:
1592
+ // //
1593
+ // // originalPath:
1594
+ // // src/components/Home
1595
+ // //
1596
+ // // parent directory:
1597
+ // // src/components
1598
+ // // ----------------------------------------------------------
1599
+ // const parentDirectory = path.dirname(absoluteOriginalPath);
1600
+ // fs.mkdirSync(parentDirectory, {
1601
+ // recursive: true,
1602
+ // });
1603
+ // // ----------------------------------------------------------
1604
+ // // STEP 4:
1605
+ // // Move the directory back to its original location.
1606
+ // // This restores both location and name.
1607
+ // // ----------------------------------------------------------
1608
+ // fs.renameSync(absoluteTrashPath, absoluteOriginalPath);
1609
+ // // ----------------------------------------------------------
1610
+ // // STEP 5:
1611
+ // // Return success.
1612
+ // // ----------------------------------------------------------
1613
+ // return {
1614
+ // success: true,
1615
+ // trashPath,
1616
+ // originalPath,
1617
+ // };
1618
+ // }
1619
+ /**
1620
+ * Restores a file from .looma-trash to its original location.
1621
+ *
1622
+ * Params:
1623
+ * - trashPath:
1624
+ * Relative path of the file inside .looma-trash.
1625
+ *
1626
+ * - originalPath:
1627
+ * Original relative path of the file before deletion.
1628
+ *
1629
+ * Returns:
1630
+ * {
1631
+ * success: boolean,
1632
+ * trashPath: string,
1633
+ * originalPath: string
1634
+ * }
1635
+ */
1636
+ // function restoreFile({ trashPath, originalPath }) {
1637
+ // // ----------------------------------------------------------
1638
+ // // STEP 1:
1639
+ // // Convert relative paths to absolute paths.
1640
+ // // ----------------------------------------------------------
1641
+ // const absoluteTrashPath = path.resolve(process.cwd(), trashPath);
1642
+ // const absoluteOriginalPath = path.resolve(process.cwd(), originalPath);
1643
+ // // ----------------------------------------------------------
1644
+ // // STEP 2:
1645
+ // // Verify that the file exists in trash.
1646
+ // // ----------------------------------------------------------
1647
+ // if (!fs.existsSync(absoluteTrashPath)) {
1648
+ // return {
1649
+ // success: false,
1650
+ // message: "File does not exist in trash",
1651
+ // trashPath,
1652
+ // originalPath,
1653
+ // };
1654
+ // }
1655
+ // // ----------------------------------------------------------
1656
+ // // STEP 3:
1657
+ // // Ensure parent directory exists.
1658
+ // //
1659
+ // // Example:
1660
+ // //
1661
+ // // originalPath:
1662
+ // // src/App/Header.tsx
1663
+ // //
1664
+ // // parent directory:
1665
+ // // src/App
1666
+ // // ----------------------------------------------------------
1667
+ // const parentDirectory = path.dirname(absoluteOriginalPath);
1668
+ // fs.mkdirSync(parentDirectory, {
1669
+ // recursive: true,
1670
+ // });
1671
+ // // ----------------------------------------------------------
1672
+ // // STEP 4:
1673
+ // // Restore the file to its original path.
1674
+ // // ----------------------------------------------------------
1675
+ // fs.renameSync(absoluteTrashPath, absoluteOriginalPath);
1676
+ // // ----------------------------------------------------------
1677
+ // // STEP 5:
1678
+ // // Return success.
1679
+ // // ----------------------------------------------------------
1680
+ // return {
1681
+ // success: true,
1682
+ // trashPath,
1683
+ // originalPath,
1684
+ // };
1685
+ // }
1686
+ function undoUpdateComponent(operation, appContext) {
1687
+ const { componentPath } = operation.target;
1688
+ const { componentCode } = operation.before;
1689
+ fs.writeFileSync(componentPath, componentCode, "utf8");
1690
+ return {
1691
+ success: true,
1692
+ componentPath,
1693
+ };
1694
+ }
1695
+ const undoHandlers = {
1696
+ // removeImport: (operation, appContext) => {
1697
+ // undoRemoveImport(operation, appContext);
1698
+ // },
1699
+ moveComponent: (operation, appContext) => {
1700
+ undoMoveComponent(operation, appContext);
1701
+ },
1702
+ renameComponent: (operation, appContext) => {
1703
+ undoRenameComponent(operation, appContext);
1704
+ },
1705
+ createComponent: (operation, appContext) => {
1706
+ undoCreateComponent(operation, appContext);
1707
+ },
1708
+ deleteComponent: (operation, appContext) => {
1709
+ undoDeleteComponent(operation, appContext);
1710
+ },
1711
+ // insertVariable: (operation, appContext) => {
1712
+ // undoInsertVariable(operation, appContext);
1713
+ // },
1714
+ // updateVariable: (operation, appContext) => {
1715
+ // undoUpdateVariable(operation, appContext);
1716
+ // },
1717
+ // deleteVariable: (operation, appContext) => {
1718
+ // undoDeleteVariable(operation, appContext);
1719
+ // },
1720
+ // insertCode: (operation, appContext) => {
1721
+ // undoInsertCode(operation, appContext);
1722
+ // },
1723
+ extractComponent: (operation, appContext) => {
1724
+ undoExtractComponent(operation, appContext);
1725
+ },
1726
+ // insertJSX: (operation, appContext) => {
1727
+ // undoInsertJSX(operation, appContext);
1728
+ // },
1729
+ // replaceJSX: (operation, appContext) => {
1730
+ // undoReplaceJSX(operation, appContext);
1731
+ // },
1732
+ // removeJSX: (operation, appContext) => {
1733
+ // undoRemoveJSX(operation, appContext);
1734
+ // },
1735
+ // moveJSX: (operation, appContext) => {
1736
+ // undoMoveJSX(operation, appContext);
1737
+ // },
1738
+ // wrapJSX: (operation, appContext) => {
1739
+ // undoWrapJSX(operation, appContext);
1740
+ // },
1741
+ updateComponent: (operation, appContext) => {
1742
+ undoUpdateComponent(operation, appContext);
1743
+ },
1744
+ // normalizeComponent: (operation, appContext) => {
1745
+ // undoNormalizeComponent(operation, appContext);
1746
+ // },
1747
+ createFile: (operation, appContext) => {
1748
+ undoCreateFile(operation, appContext);
1749
+ },
1750
+ deleteFile: (operation, appContext) => {
1751
+ undoDeleteFile(operation, appContext);
1752
+ },
1753
+ renameFile: (operation, appContext) => {
1754
+ undoRenameFile(operation, appContext);
1755
+ },
1756
+ moveFile: (operation, appContext) => {
1757
+ undoMoveFile(operation, appContext);
1758
+ },
1759
+ createDirectory: (operation, appContext) => {
1760
+ undoCreateDirectory(operation, appContext);
1761
+ },
1762
+ deleteDirectory: (operation, appContext) => {
1763
+ undoDeleteDirectory(operation, appContext);
1764
+ },
1765
+ renameDirectory: (operation, appContext) => {
1766
+ undoRenameDirectory(operation, appContext);
1767
+ },
1768
+ moveDirectory: (operation, appContext) => {
1769
+ undoMoveDirectory(operation, appContext);
1770
+ },
1771
+ // insertStyles: (operation, appContext) => {
1772
+ // undoInsertStyles(operation, appContext);
1773
+ // },
1774
+ updateStyles: (operation, appContext) => {
1775
+ undoUpdateStyles(operation, appContext);
1776
+ },
1777
+ removeStyles: (operation, appContext) => {
1778
+ undoRemoveStyles(operation, appContext);
1779
+ },
1780
+ renameCssClass: (operation, appContext) => {
1781
+ undoRenameCssClass(operation, appContext);
1782
+ },
1783
+ // syncComponentStyles: (operation, appContext) => {
1784
+ // undoSyncComponentStyles(operation, appContext);
1785
+ // },
1786
+ // resolveCssClassConflicts: (operation, appContext) => {
1787
+ // undoResolveCssClassConflicts(operation, appContext);
1788
+ // },
1789
+ // resolveStyleDependencies: (operation, appContext) => {
1790
+ // undoResolveStyleDependencies(operation, appContext);
1791
+ // },
1792
+ // optimizeImports: (operation, appContext) => {
1793
+ // undoOptimizeImports(operation, appContext);
1794
+ // },
1795
+ };
1796
+ function redoUpdateComponent(operation, appContext) {
1797
+ const { componentPath } = operation.target;
1798
+ const { componentCode } = operation.after;
1799
+ fs.writeFileSync(componentPath, componentCode, "utf8");
1800
+ return {
1801
+ success: true,
1802
+ componentPath,
1803
+ };
1804
+ }
1805
+ function redoMoveComponent(operation, appContext) {
1806
+ // ----------------------------------------------------------
1807
+ // STEP 1:
1808
+ // Extract paths from operation
1809
+ // ----------------------------------------------------------
1810
+ const { sourcePath, destinationPath } = operation.target;
1811
+ // ----------------------------------------------------------
1812
+ // STEP 2:
1813
+ // Resolve component name
1814
+ // ----------------------------------------------------------
1815
+ //
1816
+ // Example:
1817
+ //
1818
+ // ../../src/components/Header
1819
+ //
1820
+ // -> Header
1821
+ //
1822
+ // ----------------------------------------------------------
1823
+ const componentName = path.basename(sourcePath);
1824
+ // ----------------------------------------------------------
1825
+ // STEP 3:
1826
+ // Ensure component exists at original location
1827
+ // ----------------------------------------------------------
1828
+ if (!fs.existsSync(sourcePath)) {
1829
+ throw new LoomaError(ERROR_CODES.COMPONENT_NOT_FOUND, `Component not found: ${sourcePath}`);
1830
+ }
1831
+ // ----------------------------------------------------------
1832
+ // STEP 4:
1833
+ // Ensure destination directory exists
1834
+ // ----------------------------------------------------------
1835
+ fs.mkdirSync(destinationPath, {
1836
+ recursive: true,
1837
+ });
1838
+ // ----------------------------------------------------------
1839
+ // STEP 5:
1840
+ // Build final moved location
1841
+ // ----------------------------------------------------------
1842
+ //
1843
+ // Example:
1844
+ //
1845
+ // destinationPath/Header
1846
+ //
1847
+ // ----------------------------------------------------------
1848
+ const movedComponentPath = path.join(destinationPath, componentName);
1849
+ // ----------------------------------------------------------
1850
+ // STEP 6:
1851
+ // Move component again
1852
+ // ----------------------------------------------------------
1853
+ fs.renameSync(sourcePath, movedComponentPath);
1854
+ // ----------------------------------------------------------
1855
+ // STEP 7:
1856
+ // Return redo result
1857
+ // ----------------------------------------------------------
1858
+ return {
1859
+ success: true,
1860
+ movedPath: movedComponentPath,
1861
+ };
1862
+ }
1863
+ function redoRenameComponent(operation, appContext) {
1864
+ // ----------------------------------------------------------
1865
+ // STEP 1:
1866
+ // Extract information from operation log.
1867
+ // ----------------------------------------------------------
1868
+ const { newComponentPath: componentPath } = operation.target;
1869
+ const { componentName: oldComponentName } = operation.before;
1870
+ const { componentName: newComponentName } = operation.after;
1871
+ // ----------------------------------------------------------
1872
+ // STEP 2:
1873
+ // Re-apply the original rename.
1874
+ // ----------------------------------------------------------
1875
+ const result = mutations.renameComponent({
1876
+ componentPath,
1877
+ newComponentName,
1878
+ // Preserve the same behavior used
1879
+ // during the original rename.
1880
+ updateComponentCode: true,
1881
+ }, appContext);
1882
+ // ----------------------------------------------------------
1883
+ // STEP 3:
1884
+ // Validate redo.
1885
+ // ----------------------------------------------------------
1886
+ if (!result?.success) {
1887
+ throw new LoomaError(ERROR_CODES.REDO_FAILED, `Failed to redo renameComponent: ${oldComponentName} -> ${newComponentName}`);
1888
+ }
1889
+ // ----------------------------------------------------------
1890
+ // STEP 4:
1891
+ // Return result.
1892
+ // ----------------------------------------------------------
1893
+ return {
1894
+ success: true,
1895
+ componentPath,
1896
+ };
1897
+ }
1898
+ function redoCreateComponent(operation, appContext) {
1899
+ // ----------------------------------------------------------
1900
+ // STEP 1:
1901
+ // Extract information from operation log
1902
+ // ----------------------------------------------------------
1903
+ const { componentName, componentCode, parentDirectory } = operation.after;
1904
+ // ----------------------------------------------------------
1905
+ // STEP 2:
1906
+ // Recreate component
1907
+ // ----------------------------------------------------------
1908
+ const result = mutations.createComponent({
1909
+ componentName,
1910
+ componentCode,
1911
+ parentDirectory,
1912
+ }, appContext);
1913
+ // ----------------------------------------------------------
1914
+ // STEP 3:
1915
+ // Validate redo
1916
+ // ----------------------------------------------------------
1917
+ if (!result?.success) {
1918
+ throw new LoomaError(ERROR_CODES.REDO_FAILED, `Failed to redo createComponent: ${componentName}`);
1919
+ }
1920
+ // ----------------------------------------------------------
1921
+ // STEP 4:
1922
+ // Return result
1923
+ // ----------------------------------------------------------
1924
+ return {
1925
+ success: true,
1926
+ componentDirectoryPath: result.componentDirectoryPath,
1927
+ };
1928
+ }
1929
+ function redoDeleteComponent(operation, appContext) {
1930
+ // ----------------------------------------------------------
1931
+ // STEP 1:
1932
+ // Resolve original component path.
1933
+ //
1934
+ // Example:
1935
+ //
1936
+ // src/components/Home
1937
+ //
1938
+ // ----------------------------------------------------------
1939
+ const sourcePath = path.resolve(appContext.project.root, operation.target.componentDirectoryPath);
1940
+ // ----------------------------------------------------------
1941
+ // STEP 2:
1942
+ // Resolve trash location.
1943
+ //
1944
+ // Example:
1945
+ //
1946
+ // .looma-trash/1780467601246_Home
1947
+ //
1948
+ // ----------------------------------------------------------
1949
+ const destinationPath = path.resolve(appContext.project.root, operation.after.trashPath);
1950
+ // ----------------------------------------------------------
1951
+ // STEP 3:
1952
+ // Ensure trash parent directory exists.
1953
+ // ----------------------------------------------------------
1954
+ const trashParentDirectory = path.dirname(destinationPath);
1955
+ fs.mkdirSync(trashParentDirectory, {
1956
+ recursive: true,
1957
+ });
1958
+ // ----------------------------------------------------------
1959
+ // STEP 4:
1960
+ // Ensure component still exists.
1961
+ // ----------------------------------------------------------
1962
+ if (!fs.existsSync(sourcePath)) {
1963
+ throw new LoomaError(ERROR_CODES.COMPONENT_NOT_FOUND, `Component not found: ${sourcePath}`);
1964
+ }
1965
+ // ----------------------------------------------------------
1966
+ // STEP 5:
1967
+ // Move component back to trash.
1968
+ // ----------------------------------------------------------
1969
+ fs.renameSync(sourcePath, destinationPath);
1970
+ // ----------------------------------------------------------
1971
+ // STEP 6:
1972
+ // Return redo result.
1973
+ // ----------------------------------------------------------
1974
+ return {
1975
+ success: true,
1976
+ sourcePath,
1977
+ destinationPath,
1978
+ };
1979
+ }
1980
+ // function redoInsertVariable(operation, appContext) {}
1981
+ // function redoUpdateVariable(operation, appContext) {}
1982
+ // function redoDeleteVariable(operation, appContext) {}
1983
+ // function redoInsertCode(operation, appContext) {}
1984
+ function redoExtractComponent(operation, appContext) { }
1985
+ // function redoInsertJSX(operation, appContext) {}
1986
+ // function redoReplaceJSX(operation, appContext) {}
1987
+ // function redoRemoveJSX(operation, appContext) {}
1988
+ // function redoMoveJSX(operation, appContext) {}
1989
+ // function redoWrapJSX(operation, appContext) {}
1990
+ function redoCreateFile(operation, appContext) {
1991
+ // ----------------------------------------------------------
1992
+ // STEP 1:
1993
+ // Extract information from operation log
1994
+ // ----------------------------------------------------------
1995
+ const { filePath } = operation.target;
1996
+ const { fileContent } = operation.after;
1997
+ // ----------------------------------------------------------
1998
+ // STEP 2:
1999
+ // Ensure parent directory exists
2000
+ // ----------------------------------------------------------
2001
+ const parentDirectory = path.dirname(filePath);
2002
+ fs.mkdirSync(parentDirectory, {
2003
+ recursive: true,
2004
+ });
2005
+ // ----------------------------------------------------------
2006
+ // STEP 3:
2007
+ // Ensure file does not already exist
2008
+ // ----------------------------------------------------------
2009
+ if (fs.existsSync(filePath)) {
2010
+ throw new LoomaError(ERROR_CODES.FILE_ALREADY_EXISTS, `File already exists: ${filePath}`);
2011
+ }
2012
+ // ----------------------------------------------------------
2013
+ // STEP 4:
2014
+ // Recreate file
2015
+ // ----------------------------------------------------------
2016
+ fs.writeFileSync(filePath, fileContent, "utf8");
2017
+ // ----------------------------------------------------------
2018
+ // STEP 5:
2019
+ // Return redo result
2020
+ // ----------------------------------------------------------
2021
+ return {
2022
+ success: true,
2023
+ createdFile: filePath,
2024
+ };
2025
+ }
2026
+ function redoDeleteFile(operation, appContext) {
2027
+ // ----------------------------------------------------------
2028
+ // STEP 1:
2029
+ // Extract file paths
2030
+ // ----------------------------------------------------------
2031
+ const { originalPath, trashPath } = operation.target;
2032
+ // ----------------------------------------------------------
2033
+ // STEP 2:
2034
+ // Ensure original file exists
2035
+ // ----------------------------------------------------------
2036
+ if (!fs.existsSync(originalPath)) {
2037
+ throw new LoomaError(ERROR_CODES.FILE_NOT_FOUND, `Original file not found: ${originalPath}`);
2038
+ }
2039
+ // ----------------------------------------------------------
2040
+ // STEP 3:
2041
+ // Ensure trash parent directory exists
2042
+ // ----------------------------------------------------------
2043
+ const trashParentDirectory = path.dirname(trashPath);
2044
+ fs.mkdirSync(trashParentDirectory, {
2045
+ recursive: true,
2046
+ });
2047
+ // ----------------------------------------------------------
2048
+ // STEP 4:
2049
+ // Move file back into trash
2050
+ // ----------------------------------------------------------
2051
+ fs.renameSync(originalPath, trashPath);
2052
+ // ----------------------------------------------------------
2053
+ // STEP 5:
2054
+ // Return redo result
2055
+ // ----------------------------------------------------------
2056
+ return {
2057
+ success: true,
2058
+ deletedFile: originalPath,
2059
+ };
2060
+ }
2061
+ function redoRenameFile(operation, appContext) {
2062
+ // ----------------------------------------------------------
2063
+ // STEP 1:
2064
+ // Extract file paths
2065
+ // ----------------------------------------------------------
2066
+ const { oldFilePath, newFilePath } = operation.target;
2067
+ // ----------------------------------------------------------
2068
+ // STEP 2:
2069
+ // Ensure original file exists
2070
+ // ----------------------------------------------------------
2071
+ if (!fs.existsSync(oldFilePath)) {
2072
+ throw new LoomaError(ERROR_CODES.FILE_NOT_FOUND, `Original file not found: ${oldFilePath}`);
2073
+ }
2074
+ // ----------------------------------------------------------
2075
+ // STEP 3:
2076
+ // Ensure new parent directory exists
2077
+ // ----------------------------------------------------------
2078
+ const parentDirectory = path.dirname(newFilePath);
2079
+ fs.mkdirSync(parentDirectory, {
2080
+ recursive: true,
2081
+ });
2082
+ // ----------------------------------------------------------
2083
+ // STEP 4:
2084
+ // Rename file again
2085
+ // ----------------------------------------------------------
2086
+ fs.renameSync(oldFilePath, newFilePath);
2087
+ // ----------------------------------------------------------
2088
+ // STEP 5:
2089
+ // Return redo result
2090
+ // ----------------------------------------------------------
2091
+ return {
2092
+ success: true,
2093
+ renamedFile: newFilePath,
2094
+ };
2095
+ }
2096
+ function redoMoveFile(operation, appContext) {
2097
+ // ----------------------------------------------------------
2098
+ // STEP 1:
2099
+ // Extract file paths
2100
+ // ----------------------------------------------------------
2101
+ const { sourcePath, destinationPath } = operation.target;
2102
+ // ----------------------------------------------------------
2103
+ // STEP 2:
2104
+ // Ensure original file exists
2105
+ // ----------------------------------------------------------
2106
+ if (!fs.existsSync(sourcePath)) {
2107
+ throw new LoomaError(ERROR_CODES.FILE_NOT_FOUND, `Original file not found: ${sourcePath}`);
2108
+ }
2109
+ // ----------------------------------------------------------
2110
+ // STEP 3:
2111
+ // Resolve moved file path
2112
+ // ----------------------------------------------------------
2113
+ //
2114
+ // Example:
2115
+ //
2116
+ // sourcePath:
2117
+ // /src/tasks/helpers/api.js
2118
+ //
2119
+ // destinationPath:
2120
+ // /src/services
2121
+ //
2122
+ // moved file:
2123
+ // /src/services/api.js
2124
+ //
2125
+ // ----------------------------------------------------------
2126
+ const fileName = path.basename(sourcePath);
2127
+ const movedFilePath = path.join(destinationPath, fileName);
2128
+ // ----------------------------------------------------------
2129
+ // STEP 4:
2130
+ // Ensure destination directory exists
2131
+ // ----------------------------------------------------------
2132
+ fs.mkdirSync(destinationPath, {
2133
+ recursive: true,
2134
+ });
2135
+ // ----------------------------------------------------------
2136
+ // STEP 5:
2137
+ // Move file again
2138
+ // ----------------------------------------------------------
2139
+ fs.renameSync(sourcePath, movedFilePath);
2140
+ // ----------------------------------------------------------
2141
+ // STEP 6:
2142
+ // Return redo result
2143
+ // ----------------------------------------------------------
2144
+ return {
2145
+ success: true,
2146
+ movedFile: movedFilePath,
2147
+ };
2148
+ }
2149
+ function redoCreateDirectory(operation, appContext) {
2150
+ // ----------------------------------------------------------
2151
+ // STEP 1:
2152
+ // Extract paths
2153
+ // ----------------------------------------------------------
2154
+ const { directoryPath, trashPath } = operation.target;
2155
+ // ----------------------------------------------------------
2156
+ // STEP 2:
2157
+ // Ensure trashed directory exists
2158
+ // ----------------------------------------------------------
2159
+ if (!fs.existsSync(trashPath)) {
2160
+ throw new LoomaError(ERROR_CODES.DIRECTORY_NOT_FOUND, `Directory not found in trash: ${trashPath}`);
2161
+ }
2162
+ // ----------------------------------------------------------
2163
+ // STEP 3:
2164
+ // Ensure destination parent exists
2165
+ // ----------------------------------------------------------
2166
+ fs.mkdirSync(path.dirname(directoryPath), {
2167
+ recursive: true,
2168
+ });
2169
+ // ----------------------------------------------------------
2170
+ // STEP 4:
2171
+ // Restore directory
2172
+ // ----------------------------------------------------------
2173
+ fs.renameSync(trashPath, directoryPath);
2174
+ // ----------------------------------------------------------
2175
+ // STEP 5:
2176
+ // Return result
2177
+ // ----------------------------------------------------------
2178
+ return {
2179
+ success: true,
2180
+ restoredDirectory: directoryPath,
2181
+ };
2182
+ }
2183
+ function redoDeleteDirectory(operation, appContext) {
2184
+ // ----------------------------------------------------------
2185
+ // STEP 1:
2186
+ // Extract directory paths
2187
+ // ----------------------------------------------------------
2188
+ const { originalPath, trashPath } = operation.target;
2189
+ // ----------------------------------------------------------
2190
+ // STEP 2:
2191
+ // Ensure original directory exists
2192
+ // ----------------------------------------------------------
2193
+ if (!fs.existsSync(originalPath)) {
2194
+ throw new LoomaError(ERROR_CODES.DIRECTORY_NOT_FOUND, `Original directory not found: ${originalPath}`);
2195
+ }
2196
+ // ----------------------------------------------------------
2197
+ // STEP 3:
2198
+ // Ensure trash parent directory exists
2199
+ // ----------------------------------------------------------
2200
+ const trashParentDirectory = path.dirname(trashPath);
2201
+ fs.mkdirSync(trashParentDirectory, {
2202
+ recursive: true,
2203
+ });
2204
+ // ----------------------------------------------------------
2205
+ // STEP 4:
2206
+ // Move directory back to trash
2207
+ // ----------------------------------------------------------
2208
+ fs.renameSync(originalPath, trashPath);
2209
+ // ----------------------------------------------------------
2210
+ // STEP 5:
2211
+ // Return redo result
2212
+ // ----------------------------------------------------------
2213
+ return {
2214
+ success: true,
2215
+ deletedDirectory: originalPath,
2216
+ };
2217
+ }
2218
+ function redoRenameDirectory(operation, appContext) {
2219
+ // ----------------------------------------------------------
2220
+ // STEP 1:
2221
+ // Extract directory paths
2222
+ // ----------------------------------------------------------
2223
+ const { oldDirectoryPath, newDirectoryPath } = operation.target;
2224
+ // ----------------------------------------------------------
2225
+ // STEP 2:
2226
+ // Ensure original directory exists
2227
+ // ----------------------------------------------------------
2228
+ if (!fs.existsSync(oldDirectoryPath)) {
2229
+ throw new LoomaError(ERROR_CODES.DIRECTORY_NOT_FOUND, `Original directory not found: ${oldDirectoryPath}`);
2230
+ }
2231
+ // ----------------------------------------------------------
2232
+ // STEP 3:
2233
+ // Ensure new parent directory exists
2234
+ // ----------------------------------------------------------
2235
+ const parentDirectory = path.dirname(newDirectoryPath);
2236
+ fs.mkdirSync(parentDirectory, {
2237
+ recursive: true,
2238
+ });
2239
+ // ----------------------------------------------------------
2240
+ // STEP 4:
2241
+ // Reapply rename
2242
+ // ----------------------------------------------------------
2243
+ fs.renameSync(oldDirectoryPath, newDirectoryPath);
2244
+ // ----------------------------------------------------------
2245
+ // STEP 5:
2246
+ // Return redo result
2247
+ // ----------------------------------------------------------
2248
+ return {
2249
+ success: true,
2250
+ renamedDirectory: newDirectoryPath,
2251
+ };
2252
+ }
2253
+ function redoMoveDirectory(operation, appContext) {
2254
+ // ----------------------------------------------------------
2255
+ // STEP 1:
2256
+ // Extract paths
2257
+ // ----------------------------------------------------------
2258
+ const { sourcePath, destinationPath } = operation.target;
2259
+ // ----------------------------------------------------------
2260
+ // STEP 2:
2261
+ // Ensure original directory exists
2262
+ // ----------------------------------------------------------
2263
+ if (!fs.existsSync(sourcePath)) {
2264
+ throw new LoomaError(ERROR_CODES.DIRECTORY_NOT_FOUND, `Original directory not found: ${sourcePath}`);
2265
+ }
2266
+ // ----------------------------------------------------------
2267
+ // STEP 3:
2268
+ // Determine moved directory path
2269
+ // ----------------------------------------------------------
2270
+ //
2271
+ // Example:
2272
+ //
2273
+ // sourcePath:
2274
+ // src/components/Header
2275
+ //
2276
+ // destinationPath:
2277
+ // src/layout
2278
+ //
2279
+ // movedDirectoryPath:
2280
+ // src/layout/Header
2281
+ //
2282
+ // ----------------------------------------------------------
2283
+ const directoryName = path.basename(sourcePath);
2284
+ const movedDirectoryPath = path.join(destinationPath, directoryName);
2285
+ // ----------------------------------------------------------
2286
+ // STEP 4:
2287
+ // Ensure destination directory exists
2288
+ // ----------------------------------------------------------
2289
+ fs.mkdirSync(destinationPath, {
2290
+ recursive: true,
2291
+ });
2292
+ // ----------------------------------------------------------
2293
+ // STEP 5:
2294
+ // Move directory again
2295
+ // ----------------------------------------------------------
2296
+ fs.renameSync(sourcePath, movedDirectoryPath);
2297
+ // ----------------------------------------------------------
2298
+ // STEP 6:
2299
+ // Return redo result
2300
+ // ----------------------------------------------------------
2301
+ return {
2302
+ success: true,
2303
+ movedDirectory: movedDirectoryPath,
2304
+ };
2305
+ }
2306
+ function redoUpdateStyles(operation, appContext) {
2307
+ try {
2308
+ // ----------------------------------------------------------
2309
+ // STEP 1:
2310
+ // Extract CSS file path
2311
+ // ----------------------------------------------------------
2312
+ const { cssPath } = operation.target;
2313
+ // ----------------------------------------------------------
2314
+ // STEP 2:
2315
+ // Extract original CSS content
2316
+ // ----------------------------------------------------------
2317
+ const originalCss = operation.before.cssCode;
2318
+ const newCss = operation.after.cssCode;
2319
+ // ----------------------------------------------------------
2320
+ // STEP 3:
2321
+ // Ensure rollback snapshot exists
2322
+ // ----------------------------------------------------------
2323
+ if (typeof newCss !== "string") {
2324
+ throw new LoomaError(ERROR_CODES.CSS_NOT_FOUND, "Missing new CSS code for Redo.");
2325
+ }
2326
+ // ----------------------------------------------------------
2327
+ // STEP 4:
2328
+ // Restore original CSS content
2329
+ // ----------------------------------------------------------
2330
+ fs.writeFileSync(cssPath, newCss, "utf8");
2331
+ // ----------------------------------------------------------
2332
+ // STEP 5:
2333
+ // Return rollback result
2334
+ // ----------------------------------------------------------
2335
+ return {
2336
+ success: true,
2337
+ newCssFile: cssPath,
2338
+ };
2339
+ }
2340
+ catch (error) {
2341
+ return {
2342
+ success: false,
2343
+ error,
2344
+ };
2345
+ }
2346
+ }
2347
+ function redoRemoveStyles(operation, appContext) {
2348
+ // ----------------------------------------------------------
2349
+ // STEP 1:
2350
+ // Extract CSS file path
2351
+ // ----------------------------------------------------------
2352
+ const { cssPath } = operation.target;
2353
+ // ----------------------------------------------------------
2354
+ // STEP 2:
2355
+ // Extract CSS snapshot after removal
2356
+ // ----------------------------------------------------------
2357
+ const removedCss = operation.after.cssCode;
2358
+ // ----------------------------------------------------------
2359
+ // STEP 3:
2360
+ // Ensure redo snapshot exists
2361
+ // ----------------------------------------------------------
2362
+ if (typeof removedCss !== "string") {
2363
+ throw new LoomaError(ERROR_CODES.CSS_NOT_FOUND, "Missing CSS code for redo.");
2364
+ }
2365
+ // ----------------------------------------------------------
2366
+ // STEP 4:
2367
+ // Reapply removed styles
2368
+ // ----------------------------------------------------------
2369
+ fs.writeFileSync(cssPath, removedCss, "utf8");
2370
+ // ----------------------------------------------------------
2371
+ // STEP 5:
2372
+ // Return redo result
2373
+ // ----------------------------------------------------------
2374
+ return {
2375
+ success: true,
2376
+ updatedCssFile: cssPath,
2377
+ };
2378
+ }
2379
+ function redoRenameCssClass(operation, appContext) {
2380
+ // ----------------------------------------------------------
2381
+ // STEP 1:
2382
+ // Extract target files
2383
+ // ----------------------------------------------------------
2384
+ const { cssPath, componentJSXPath } = operation.target;
2385
+ // ----------------------------------------------------------
2386
+ // STEP 2:
2387
+ // Extract updated contents
2388
+ // ----------------------------------------------------------
2389
+ const { cssCode, jsxCode } = operation.after;
2390
+ // ----------------------------------------------------------
2391
+ // STEP 3:
2392
+ // Validate snapshots
2393
+ // ----------------------------------------------------------
2394
+ if (typeof cssCode !== "string") {
2395
+ throw new LoomaError(ERROR_CODES.CSS_NOT_FOUND, "Missing cssCode in operation.after");
2396
+ }
2397
+ if (typeof jsxCode !== "string") {
2398
+ throw new LoomaError(ERROR_CODES.JSX_NOT_FOUND, "Missing jsxCode in operation.after");
2399
+ }
2400
+ // ----------------------------------------------------------
2401
+ // STEP 4:
2402
+ // Reapply CSS changes
2403
+ // ----------------------------------------------------------
2404
+ fs.writeFileSync(cssPath, cssCode, "utf8");
2405
+ // ----------------------------------------------------------
2406
+ // STEP 5:
2407
+ // Reapply JSX changes
2408
+ // ----------------------------------------------------------
2409
+ fs.writeFileSync(componentJSXPath, jsxCode, "utf8");
2410
+ // ----------------------------------------------------------
2411
+ // STEP 6:
2412
+ // Return result
2413
+ // ----------------------------------------------------------
2414
+ return {
2415
+ success: true,
2416
+ cssPath,
2417
+ componentJSXPath,
2418
+ };
2419
+ }
2420
+ const redoHandlers = {
2421
+ // normalizeComponent: (operation, appContext) => {
2422
+ //redoNormalizeComponent(operation, appContext);
2423
+ // },
2424
+ updateComponent: (operation, appContext) => {
2425
+ redoUpdateComponent(operation, appContext);
2426
+ },
2427
+ moveComponent: (operation, appContext) => {
2428
+ redoMoveComponent(operation, appContext);
2429
+ },
2430
+ renameComponent: (operation, appContext) => {
2431
+ redoRenameComponent(operation, appContext);
2432
+ },
2433
+ createComponent: (operation, appContext) => {
2434
+ redoCreateComponent(operation, appContext);
2435
+ },
2436
+ deleteComponent: (operation, appContext) => {
2437
+ redoDeleteComponent(operation, appContext);
2438
+ },
2439
+ // insertVariable: (operation, appContext) => {
2440
+ // redoInsertVariable(operation, appContext);
2441
+ // },
2442
+ // updateVariable: (operation, appContext) => {
2443
+ // redoUpdateVariable(operation, appContext);
2444
+ // },
2445
+ // deleteVariable: (operation, appContext) => {
2446
+ // redoDeleteVariable(operation, appContext);
2447
+ // },
2448
+ // insertCode: (operation, appContext) => {
2449
+ // redoInsertCode(operation, appContext);
2450
+ // },
2451
+ extractComponent: (operation, appContext) => {
2452
+ redoExtractComponent(operation, appContext);
2453
+ },
2454
+ // insertJSX: (operation, appContext) => {
2455
+ // redoInsertJSX(operation, appContext);
2456
+ // },
2457
+ // replaceJSX: (operation, appContext) => {
2458
+ // redoReplaceJSX(operation, appContext);
2459
+ // },
2460
+ // removeJSX: (operation, appContext) => {
2461
+ // redoRemoveJSX(operation, appContext);
2462
+ // },
2463
+ // moveJSX: (operation, appContext) => {
2464
+ // redoMoveJSX(operation, appContext);
2465
+ // },
2466
+ // wrapJSX: (operation, appContext) => {
2467
+ // redoWrapJSX(operation, appContext);
2468
+ // },
2469
+ createFile: (operation, appContext) => {
2470
+ redoCreateFile(operation, appContext);
2471
+ },
2472
+ deleteFile: (operation, appContext) => {
2473
+ redoDeleteFile(operation, appContext);
2474
+ },
2475
+ renameFile: (operation, appContext) => {
2476
+ redoRenameFile(operation, appContext);
2477
+ },
2478
+ moveFile: (operation, appContext) => {
2479
+ redoMoveFile(operation, appContext);
2480
+ },
2481
+ createDirectory: (operation, appContext) => {
2482
+ redoCreateDirectory(operation, appContext);
2483
+ },
2484
+ deleteDirectory: (operation, appContext) => {
2485
+ redoDeleteDirectory(operation, appContext);
2486
+ },
2487
+ renameDirectory: (operation, appContext) => {
2488
+ redoRenameDirectory(operation, appContext);
2489
+ },
2490
+ moveDirectory: (operation, appContext) => {
2491
+ redoMoveDirectory(operation, appContext);
2492
+ },
2493
+ // insertStyles: (operation, appContext) => {
2494
+ // redoInsertStyles(operation, appContext);
2495
+ // },
2496
+ updateStyles: (operation, appContext) => {
2497
+ redoUpdateStyles(operation, appContext);
2498
+ },
2499
+ removeStyles: (operation, appContext) => {
2500
+ redoRemoveStyles(operation, appContext);
2501
+ },
2502
+ renameCssClass: (operation, appContext) => {
2503
+ redoRenameCssClass(operation, appContext);
2504
+ },
2505
+ // syncComponentStyles: (operation, appContext) => {
2506
+ // rollbackSyncComponentStyles(operation, appContext);
2507
+ // },
2508
+ // resolveCssClassConflicts: (operation, appContext) => {
2509
+ // rollbackResolveCssClassConflicts(operation, appContext);
2510
+ // },
2511
+ // resolveStyleDependencies: (operation, appContext) => {
2512
+ // rollbackResolveStyleDependencies(operation, appContext);
2513
+ // },
2514
+ // optimizeImports: (operation, appContext) => {
2515
+ // rollbackOptimizeImports(operation, appContext);
2516
+ // },
2517
+ };
2518
+ export default {
2519
+ // rollbackHandlers,
2520
+ operationSerializers,
2521
+ undoHandlers,
2522
+ redoHandlers,
2523
+ };
2524
+ //# sourceMappingURL=rollback-handlers.js.map